1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Instrument IR to perform memory checking operations.         ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                               mc_translate.c ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of MemCheck, a heavyweight Valgrind tool for
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   detecting memory errors.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2000-2013 Julian Seward
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jseward@acm.org
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h"
33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_tool_poolalloc.h"     // For mc_include.h
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_hashtable.h"     // For mc_include.h
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h"     // VG_(fnptr_to_fnentry)
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_xarray.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "mc_include.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* FIXMEs JRS 2011-June-16.
47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Check the interpretation for vector narrowing and widening ops,
49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   particularly the saturating ones.  I suspect they are either overly
50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pessimistic and/or wrong.
51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This file implements the Memcheck instrumentation, and in
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   particular contains the core of its undefined value detection
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   machinery.  For a comprehensive background of the terminology,
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   algorithms and rationale used herein, read:
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Using Valgrind to detect undefined value errors with
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     bit-precision
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Julian Seward and Nicholas Nethercote
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     2005 USENIX Annual Technical Conference (General Track),
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Anaheim, CA, USA, April 10-15, 2005.
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ----
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Here is as good a place as any to record exactly when V bits are and
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   should be checked, why, and what function is responsible.
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Memcheck complains when an undefined value is used:
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   1. In the condition of a conditional branch.  Because it could cause
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      incorrect control flow, and thus cause incorrect externally-visible
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      behaviour.  [mc_translate.c:complainIfUndefined]
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   2. As an argument to a system call, or as the value that specifies
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the system call number.  Because it could cause an incorrect
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      externally-visible side effect.  [mc_translate.c:mc_pre_reg_read]
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   3. As the address in a load or store.  Because it could cause an
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      incorrect value to be used later, which could cause externally-visible
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      behaviour (eg. via incorrect control flow or an incorrect system call
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argument)  [complainIfUndefined]
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   4. As the target address of a branch.  Because it could cause incorrect
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      control flow.  [complainIfUndefined]
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   5. As an argument to setenv, unsetenv, or putenv.  Because it could put
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an incorrect value into the external environment.
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      [mc_replace_strmem.c:VG_WRAP_FUNCTION_ZU(*, *env)]
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   6. As the index in a GETI or PUTI operation.  I'm not sure why... (njn).
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      [complainIfUndefined]
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   7. As an argument to the VALGRIND_CHECK_MEM_IS_DEFINED and
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_CHECK_VALUE_IS_DEFINED client requests.  Because the user
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      requested it.  [in memcheck.h]
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Memcheck also complains, but should not, when an undefined value is used:
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   8. As the shift value in certain SIMD shift operations (but not in the
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      standard integer shift operations).  This inconsistency is due to
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      historical reasons.)  [complainIfUndefined]
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Memcheck does not complain, but should, when an undefined value is used:
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   9. As an input to a client request.  Because the client request may
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      affect the visible behaviour -- see bug #144362 for an example
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      involving the malloc replacements in vg_replace_malloc.c and
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_NON_SIMD_CALL* requests, where an uninitialised argument
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      isn't identified.  That bug report also has some info on how to solve
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the problem.  [valgrind.h:VALGRIND_DO_CLIENT_REQUEST]
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In practice, 1 and 2 account for the vast majority of cases.
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Generation of addr-definedness, addr-validity and
123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   guard-definedness checks pertaining to loads and stores (Iex_Load,
124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Ist_Store, IRLoadG, IRStoreG, LLSC, CAS and Dirty memory
125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   loads/stores) was re-checked 11 May 2013. */
126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Forward decls                                        ---*/
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct _MCEnv;
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRType  shadowTypeV ( IRType ty );
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp  findShadowTmpB ( struct _MCEnv* mce, IRTemp orig );
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr *i128_const_zero(void);
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Memcheck running state, and tmp management.          ---*/
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Carries info about a particular tmp.  The tmp's number is not
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   recorded, as this is implied by (equal to) its index in the tmpMap
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in MCEnv.  The tmp's type is also not recorded, as this is present
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in MCEnv.sb->tyenv.
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When .kind is Orig, .shadowV and .shadowB may give the identities
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of the temps currently holding the associated definedness (shadowV)
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and origin (shadowB) values, or these may be IRTemp_INVALID if code
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to compute such values has not yet been emitted.
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When .kind is VSh or BSh then the tmp is holds a V- or B- value,
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and so .shadowV and .shadowB must be IRTemp_INVALID, since it is
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   illogical for a shadow tmp itself to be shadowed.
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum { Orig=1, VSh=2, BSh=3 }
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempKind;
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TempKind kind;
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp   shadowV;
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp   shadowB;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt;
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Carries around state during memcheck instrumentation. */
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct _MCEnv {
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* MODIFIED: the superblock being constructed.  IRStmts are
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         added. */
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRSB* sb;
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool  trace;
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         current kind and possibly shadow temps for each temp in the
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB being constructed.  Note that it does not contain the
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         type of each tmp.  If you want to know the type, look at the
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relevant entry in sb->tyenv.  It follows that at all times
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         during the instrumentation process, the valid indices for
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmpMap and sb->tyenv are identical, being 0 .. N-1 where N is
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         total number of Orig, V- and B- temps allocated so far.
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         The reason for this strange split (types in one place, all
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         other info in another) is that we need the types to be
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         attached to sb so as to make it possible to do
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "typeOfIRExpr(mce->bb->tyenv, ...)" at various places in the
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         instrumentation process. */
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XArray* /* of TempMapEnt */ tmpMap;
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* MODIFIED: indicates whether "bogus" literals have so far been
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         found.  Starts off False, and may change to True. */
196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool bogusLiterals;
197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* READONLY: indicates whether we should use expensive
199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         interpretations of integer adds, since unfortunately LLVM
200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         uses them to do ORs in some circumstances.  Defaulted to True
201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         on MacOS and False everywhere else. */
202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool useLLVMworkarounds;
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* READONLY: the guest layout.  This indicates which parts of
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the guest state should be regarded as 'always defined'. */
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VexGuestLayout* layout;
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* READONLY: the host word type.  Needed for constructing
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arguments of type 'HWord' to be passed to helper functions.
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Ity_I32 or Ity_I64 only. */
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType hWordTy;
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MCEnv;
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* SHADOW TMP MANAGEMENT.  Shadow tmps are allocated lazily (on
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   demand), as they are encountered.  This is for two reasons.
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (1) (less important reason): Many original tmps are unused due to
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   initial IR optimisation, and we do not want to spaces in tables
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tracking them.
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Shadow IRTemps are therefore allocated on demand.  mce.tmpMap is a
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   table indexed [0 .. n_types-1], which gives the current shadow for
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   each original tmp, or INVALID_IRTEMP if none is so far assigned.
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   It is necessary to support making multiple assignments to a shadow
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- specifically, after testing a shadow for definedness, it needs
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to be made defined.  But IR's SSA property disallows this.
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (2) (more important reason): Therefore, when a shadow needs to get
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a new value, a new temporary is created, the value is assigned to
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that, and the tmpMap is updated to reflect the new binding.
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A corollary is that if the tmpMap maps a given tmp to
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp_INVALID and we are hoping to read that shadow tmp, it means
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   there's a read-before-write error in the original tmps.  The IR
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sanity checker should catch all such anomalies, however.
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create a new IRTemp of type 'ty' and kind 'kind', and add it to
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   both the table in mce->sb and to our auxiliary mapping.  Note that
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   newTemp may cause mce->tmpMap to resize, hence previous results
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   from VG_(indexXA)(mce->tmpMap) are invalidated. */
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp newTemp ( MCEnv* mce, IRType ty, TempKind kind )
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word       newIx;
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt ent;
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp     tmp = newIRTemp(mce->sb->tyenv, ty);
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent.kind    = kind;
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent.shadowV = IRTemp_INVALID;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent.shadowB = IRTemp_INVALID;
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   newIx = VG_(addToXA)( mce->tmpMap, &ent );
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(newIx == (Word)tmp);
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return tmp;
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the tmp currently shadowing the given original tmp.  If none
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so far exists, allocate one.  */
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp findShadowTmpV ( MCEnv* mce, IRTemp orig )
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt* ent;
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VG_(indexXA) range-checks 'orig', hence no need to check
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      here. */
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ent->kind == Orig);
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ent->shadowV == IRTemp_INVALID) {
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmpV
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = newTemp( mce, shadowTypeV(mce->sb->tyenv->types[orig]), VSh );
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* newTemp may cause mce->tmpMap to resize, hence previous results
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         from VG_(indexXA) are invalid. */
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->kind == Orig);
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->shadowV == IRTemp_INVALID);
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent->shadowV = tmpV;
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ent->shadowV;
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Allocate a new shadow for the given original tmp.  This means any
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   previous shadow is abandoned.  This is needed because it is
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   necessary to give a new value to a shadow once it has been tested
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for undefinedness, but unfortunately IR's SSA property disallows
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this.  Instead we must abandon the old shadow, allocate a new one
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and use that instead.
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is the same as findShadowTmpV, except we don't bother to see
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if a shadow temp already existed -- we simply allocate a new one
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   regardless. */
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void newShadowTmpV ( MCEnv* mce, IRTemp orig )
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt* ent;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VG_(indexXA) range-checks 'orig', hence no need to check
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      here. */
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ent->kind == Orig);
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (1) {
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmpV
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = newTemp( mce, shadowTypeV(mce->sb->tyenv->types[orig]), VSh );
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* newTemp may cause mce->tmpMap to resize, hence previous results
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         from VG_(indexXA) are invalid. */
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->kind == Orig);
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent->shadowV = tmpV;
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- IRAtoms -- a subset of IRExprs                       ---*/
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   isIRAtom() in libvex_ir.h.  Because this instrumenter expects flat
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   input, most of this code deals in atoms.  Usefully, a value atom
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   always has a V-value which is also an atom: constants are shadowed
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by constants, and temps are shadowed by the corresponding shadow
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   temporary. */
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef  IRExpr  IRAtom;
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* (used for sanity checks only): is this an atom which looks
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   like it's from original code? */
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_Const)
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_RdTmp) {
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TempMapEnt* ent = VG_(indexXA)( mce->tmpMap, a1->Iex.RdTmp.tmp );
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ent->kind == Orig;
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* (used for sanity checks only): is this an atom which looks
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   like it's from shadow code? */
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_Const)
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_RdTmp) {
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TempMapEnt* ent = VG_(indexXA)( mce->tmpMap, a1->Iex.RdTmp.tmp );
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ent->kind == VSh || ent->kind == BSh;
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* (used for sanity checks only): check that both args are atoms and
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are identically-kinded. */
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_Const && a2->tag == Iex_Const)
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Type management                                      ---*/
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Shadow state is always accessed using integer types.  This returns
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   an integer type with the same size (as per sizeofIRType) as the
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given type.  The only valid shadow types are Bit, I8, I16, I32,
366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   I64, I128, V128, V256. */
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRType shadowTypeV ( IRType ty )
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I128: return ty;
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_F32:  return Ity_I32;
378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ity_D32:  return Ity_I32;
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_F64:  return Ity_I64;
380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ity_D64:  return Ity_I64;
381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ity_F128: return Ity_I128;
382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ity_D128: return Ity_I128;
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128: return Ity_V128;
384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ity_V256: return Ity_V256;
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: ppIRType(ty);
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(tool_panic)("memcheck:shadowTypeV");
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce a 'defined' value of the given shadow type.  Should only be
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   supplied shadow types (Bit/I8/I16/I32/UI64). */
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* definedOfType ( IRType ty ) {
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:   return IRExpr_Const(IRConst_U1(False));
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:   return IRExpr_Const(IRConst_U8(0));
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:  return IRExpr_Const(IRConst_U16(0));
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:  return IRExpr_Const(IRConst_U32(0));
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:  return IRExpr_Const(IRConst_U64(0));
399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ity_I128: return i128_const_zero();
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_V256: return IRExpr_Const(IRConst_V256(0x00000000));
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:       VG_(tool_panic)("memcheck:definedOfType");
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Constructing IR fragments                            ---*/
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add stmt to a bb */
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void stmt ( HChar cat, MCEnv* mce, IRStmt* st ) {
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mce->trace) {
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  %c: ", cat);
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRStmt(st);
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addStmtToIRSB(mce->sb, st);
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* assign value to tmp */
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid assign ( HChar cat, MCEnv* mce, IRTemp tmp, IRExpr* expr ) {
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt(cat, mce, IRStmt_WrTmp(tmp,expr));
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* build various kinds of expressions */
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define triop(_op, _arg1, _arg2, _arg3) \
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRExpr_Triop((_op),(_arg1),(_arg2),(_arg3))
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define unop(_op, _arg)          IRExpr_Unop((_op),(_arg))
432436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define mkU1(_n)                 IRExpr_Const(IRConst_U1(_n))
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkU8(_n)                 IRExpr_Const(IRConst_U8(_n))
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkU16(_n)                IRExpr_Const(IRConst_U16(_n))
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkU32(_n)                IRExpr_Const(IRConst_U32(_n))
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkU64(_n)                IRExpr_Const(IRConst_U64(_n))
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkV128(_n)               IRExpr_Const(IRConst_V128(_n))
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkexpr(_tmp)             IRExpr_RdTmp((_tmp))
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Bind the given expression to a new temporary, and return the
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   temporary.  This effectively converts an arbitrary expression into
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   an atom.
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'ty' is the type of 'e' and hence the type that the new temporary
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   needs to be.  But passing it in is redundant, since we can deduce
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the type merely by inspecting 'e'.  So at least use that fact to
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert that the two types agree. */
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* assignNew ( HChar cat, MCEnv* mce, IRType ty, IRExpr* e )
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempKind k;
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp   t;
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   tyE = typeOfIRExpr(mce->sb->tyenv, e);
453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cat) {
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 'V': k = VSh;  break;
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 'B': k = BSh;  break;
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 'C': k = Orig; break;
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* happens when we are making up new "orig"
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expressions, for IRCAS handling */
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: tl_assert(0);
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t = newTemp(mce, ty, k);
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(cat, mce, t, e);
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkexpr(t);
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Helper functions for 128-bit ops                     ---*/
471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr *i128_const_zero(void)
474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRAtom* z64 = IRExpr_Const(IRConst_U64(0));
476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return binop(Iop_64HLto128, z64, z64);
477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* There are no I128-bit loads and/or stores [as generated by any
480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   current front ends].  So we do not need to worry about that in
481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   expr2vbits_Load */
482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Constructing definedness primitive ops               ---*/
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Defined-if-either-defined --------- */
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I8, binop(Iop_And8, a1, a2));
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I16, binop(Iop_And16, a1, a2));
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, binop(Iop_And32, a1, a2));
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, binop(Iop_And64, a1, a2));
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, binop(Iop_AndV128, a1, a2));
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRAtom* mkDifDV256 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce,a1));
522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce,a2));
523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return assignNew('V', mce, Ity_V256, binop(Iop_AndV256, a1, a2));
524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Undefined-if-either-undefined --------- */
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I8, binop(Iop_Or8, a1, a2));
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I16, binop(Iop_Or16, a1, a2));
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, binop(Iop_Or32, a1, a2));
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, binop(Iop_Or64, a1, a2));
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRAtom* mkUifU128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRAtom *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6;
554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(isShadowAtom(mce,a1));
555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(isShadowAtom(mce,a2));
556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp1 = assignNew('V', mce, Ity_I64, unop(Iop_128to64, a1));
557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp2 = assignNew('V', mce, Ity_I64, unop(Iop_128HIto64, a1));
558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp3 = assignNew('V', mce, Ity_I64, unop(Iop_128to64, a2));
559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp4 = assignNew('V', mce, Ity_I64, unop(Iop_128HIto64, a2));
560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp5 = assignNew('V', mce, Ity_I64, binop(Iop_Or64, tmp1, tmp3));
561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp6 = assignNew('V', mce, Ity_I64, binop(Iop_Or64, tmp2, tmp4));
562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return assignNew('V', mce, Ity_I128, binop(Iop_64HLto128, tmp6, tmp5));
564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, binop(Iop_OrV128, a1, a2));
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRAtom* mkUifUV256 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce,a1));
574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce,a2));
575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return assignNew('V', mce, Ity_V256, binop(Iop_OrV256, a1, a2));
576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (vty) {
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:   return mkUifU8(mce, a1, a2);
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:  return mkUifU16(mce, a1, a2);
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:  return mkUifU32(mce, a1, a2);
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:  return mkUifU64(mce, a1, a2);
584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ity_I128: return mkUifU128(mce, a1, a2);
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128: return mkUifUV128(mce, a1, a2);
586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_V256: return mkUifUV256(mce, a1, a2);
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:mkUifU");
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- The Left-family of operations. --------- */
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I8, unop(Iop_Left8, a1));
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I16, unop(Iop_Left16, a1));
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, unop(Iop_Left32, a1));
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkLeft64 ( MCEnv* mce, IRAtom* a1 ) {
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, unop(Iop_Left64, a1));
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- 'Improvement' functions for AND/OR. --------- */
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ImproveAND(data, vbits) = data OR vbits.  Defined (0) data 0s give
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   defined (0); all other -> undefined (1).
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I8, binop(Iop_Or8, data, vbits));
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I16, binop(Iop_Or16, data, vbits));
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, binop(Iop_Or32, data, vbits));
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, binop(Iop_Or64, data, vbits));
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, binop(Iop_OrV128, data, vbits));
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRAtom* mkImproveANDV256 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isOriginalAtom(mce, data));
663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce, vbits));
664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(sameKindedAtoms(data, vbits));
665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return assignNew('V', mce, Ity_V256, binop(Iop_OrV256, data, vbits));
666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ImproveOR(data, vbits) = ~data OR vbits.  Defined (0) data 1s give
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   defined (0); all other -> undefined (1).
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew(
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_I8,
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Or8,
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I8, unop(Iop_Not8, data)),
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew(
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_I16,
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Or16,
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I16, unop(Iop_Not16, data)),
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew(
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_I32,
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Or32,
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I32, unop(Iop_Not32, data)),
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew(
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_I64,
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Or64,
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, unop(Iop_Not64, data)),
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew(
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_V128,
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_OrV128,
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, unop(Iop_NotV128, data)),
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRAtom* mkImproveORV256 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isOriginalAtom(mce, data));
734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce, vbits));
735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(sameKindedAtoms(data, vbits));
736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return assignNew(
737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             'V', mce, Ity_V256,
738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             binop(Iop_OrV256,
739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   assignNew('V', mce, Ity_V256, unop(Iop_NotV256, data)),
740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   vbits) );
741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Pessimising casts. --------- */
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* The function returns an expression of type DST_TY. If any of the VBITS
746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   is undefined (value == 1) the resulting expression has all bits set to
747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   1. Otherwise, all bits are 0. */
748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  src_ty;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* tmp1;
753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note, dst_ty is a shadow type, not an original type. */
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vbits));
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   src_ty = typeOfIRExpr(mce->sb->tyenv, vbits);
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fast-track some common cases */
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I32 && dst_ty == Ity_I32)
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew('V', mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I64 && dst_ty == Ity_I64)
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew('V', mce, Ity_I64, unop(Iop_CmpwNEZ64, vbits));
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I32 && dst_ty == Ity_I64) {
766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* PCast the arg, then clone it. */
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom* tmp = assignNew('V', mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew('V', mce, Ity_I64, binop(Iop_32HLto64, tmp, tmp));
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (src_ty == Ity_I32 && dst_ty == Ity_V128) {
772436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* PCast the arg, then clone it 4 times. */
773436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom* tmp = assignNew('V', mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
774436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tmp = assignNew('V', mce, Ity_I64, binop(Iop_32HLto64, tmp, tmp));
775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return assignNew('V', mce, Ity_V128, binop(Iop_64HLtoV128, tmp, tmp));
776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (src_ty == Ity_I32 && dst_ty == Ity_V256) {
779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* PCast the arg, then clone it 8 times. */
780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom* tmp = assignNew('V', mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tmp = assignNew('V', mce, Ity_I64, binop(Iop_32HLto64, tmp, tmp));
782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tmp = assignNew('V', mce, Ity_V128, binop(Iop_64HLtoV128, tmp, tmp));
783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return assignNew('V', mce, Ity_V256, binop(Iop_V128HLtoV256, tmp, tmp));
784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (src_ty == Ity_I64 && dst_ty == Ity_I32) {
787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* PCast the arg.  This gives all 0s or all 1s.  Then throw away
788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         the top half. */
789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRAtom* tmp = assignNew('V', mce, Ity_I64, unop(Iop_CmpwNEZ64, vbits));
790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return assignNew('V', mce, Ity_I32, unop(Iop_64to32, tmp));
791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Else do it the slow way .. */
794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* First of all, collapse vbits down to a single bit. */
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp1   = NULL;
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (src_ty) {
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = vbits;
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ8, vbits));
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ16, vbits));
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ32, vbits));
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ64, vbits));
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I128: {
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Gah.  Chop it in half, OR the halves together, and compare
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that with zero. */
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* tmp2 = assignNew('V', mce, Ity_I64, unop(Iop_128HIto64, vbits));
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* tmp3 = assignNew('V', mce, Ity_I64, unop(Iop_128to64, vbits));
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* tmp4 = assignNew('V', mce, Ity_I64, binop(Iop_Or64, tmp2, tmp3));
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1         = assignNew('V', mce, Ity_I1,
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       unop(Iop_CmpNEZ64, tmp4));
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRType(src_ty);
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("mkPCastTo(1)");
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(tmp1);
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now widen up to the dst type. */
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (dst_ty) {
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return tmp1;
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I8, unop(Iop_1Sto8, tmp1));
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, unop(Iop_1Sto16, tmp1));
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, unop(Iop_1Sto32, tmp1));
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, unop(Iop_1Sto64, tmp1));
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128:
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I64,  unop(Iop_1Sto64, tmp1));
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return tmp1;
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I128:
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I64,  unop(Iop_1Sto64, tmp1));
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I128, binop(Iop_64HLto128, tmp1, tmp1));
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return tmp1;
847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_V256:
848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tmp1 = assignNew('V', mce, Ity_I64,  unop(Iop_1Sto64, tmp1));
849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tmp1 = assignNew('V', mce, Ity_V128, binop(Iop_64HLtoV128,
850436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                    tmp1, tmp1));
851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tmp1 = assignNew('V', mce, Ity_V256, binop(Iop_V128HLtoV256,
852436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                    tmp1, tmp1));
853436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return tmp1;
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRType(dst_ty);
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("mkPCastTo(2)");
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Accurate interpretation of CmpEQ/CmpNE. --------- */
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Normally, we can do CmpEQ/CmpNE by doing UifU on the arguments, and
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PCasting to Ity_U1.  However, sometimes it is necessary to be more
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accurate.  The insight is that the result is defined if two
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   corresponding bits can be found, one from each argument, so that
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   both bits are defined but are different -- that makes EQ say "No"
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and NE say "Yes".  Hence, we compute an improvement term and DifD
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it onto the "normal" (UifU) result.
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The result is:
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PCastTo<1> (
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      -- naive version
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PCastTo<sz>( UifU<sz>(vxx, vyy) )
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      `DifD<sz>`
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      -- improvement term
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PCastTo<sz>( PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) ) )
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   )
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   where
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vec contains 0 (defined) bits where the corresponding arg bits
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     are defined but different, and 1 bits otherwise.
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vec = Or<sz>( vxx,   // 0 iff bit defined
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vyy,   // 0 iff bit defined
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Not<sz>(Xor<sz>( xx, yy )) // 0 iff bits different
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     If any bit of vec is 0, the result is defined and so the
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     improvement term should produce 0...0, else it should produce
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     1...1.
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Hence require for the improvement term:
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if vec == 1...1 then 1...1 else 0...0
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ->
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) )
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This was extensively re-analysed and checked on 6 July 05.
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* expensiveCmpEQorNE ( MCEnv*  mce,
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    IRType  ty,
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    IRAtom* vxx, IRAtom* vyy,
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    IRAtom* xx,  IRAtom* yy )
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *naive, *vec, *improvement_term;
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *improved, *final_cast, *top;
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opDIFD, opUIFU, opXOR, opNOT, opCMP, opOR;
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vxx));
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vyy));
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,xx));
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,yy));
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(vxx,xx));
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(vyy,yy));
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_I16:
921436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         opOR   = Iop_Or16;
922436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         opDIFD = Iop_And16;
923436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         opUIFU = Iop_Or16;
924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         opNOT  = Iop_Not16;
925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         opXOR  = Iop_Xor16;
926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         opCMP  = Iop_CmpEQ16;
927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         top    = mkU16(0xFFFF);
928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opOR   = Iop_Or32;
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opDIFD = Iop_And32;
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opUIFU = Iop_Or32;
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opNOT  = Iop_Not32;
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opXOR  = Iop_Xor32;
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCMP  = Iop_CmpEQ32;
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         top    = mkU32(0xFFFFFFFF);
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opOR   = Iop_Or64;
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opDIFD = Iop_And64;
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opUIFU = Iop_Or64;
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opNOT  = Iop_Not64;
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opXOR  = Iop_Xor64;
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCMP  = Iop_CmpEQ64;
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         top    = mkU64(0xFFFFFFFFFFFFFFFFULL);
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("expensiveCmpEQorNE");
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   naive
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkPCastTo(mce,ty,
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assignNew('V', mce, ty, binop(opUIFU, vxx, vyy)));
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vec
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew(
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           'V', mce,ty,
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop( opOR,
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assignNew('V', mce,ty, binop(opOR, vxx, vyy)),
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assignNew(
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     'V', mce,ty,
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop( opNOT,
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           assignNew('V', mce,ty, binop(opXOR, xx, yy))))));
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   improvement_term
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkPCastTo( mce,ty,
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce,Ity_I1, binop(opCMP, vec, top)));
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   improved
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew( 'V', mce,ty, binop(opDIFD, naive, improvement_term) );
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   final_cast
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkPCastTo( mce, Ity_I1, improved );
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return final_cast;
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Semi-accurate interpretation of CmpORD. --------- */
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CmpORD32{S,U} does PowerPC-style 3-way comparisons:
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CmpORD32S(x,y) = 1<<3   if  x <s y
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     = 1<<2   if  x >s y
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     = 1<<1   if  x == y
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and similarly the unsigned variant.  The default interpretation is:
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CmpORD32{S,U}#(x,y,x#,y#) = PCast(x# `UifU` y#)
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  & (7<<1)
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The "& (7<<1)" reflects the fact that all result bits except 3,2,1
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are zero and therefore defined (viz, zero).
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Also deal with a special case better:
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CmpORD32S(x,0)
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Here, bit 3 (LT) of the result is a copy of the top bit of x and
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   will be defined even if the rest of x isn't.  In which case we do:
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CmpORD32S#(x,x#,0,{impliedly 0}#)
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = PCast(x#) & (3<<1)      -- standard interp for GT#,EQ#
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | (x# >>u 31) << 3      -- LT# = x#[31]
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Analogous handling for CmpORD64{S,U}.
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU32 ( IRAtom* e )
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toBool( e->tag == Iex_Const
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && e->Iex.Const.con->tag == Ico_U32
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && e->Iex.Const.con->Ico.U32 == 0 );
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU64 ( IRAtom* e )
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toBool( e->tag == Iex_Const
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && e->Iex.Const.con->tag == Ico_U64
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && e->Iex.Const.con->Ico.U64 == 0 );
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* doCmpORD ( MCEnv*  mce,
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IROp    cmp_op,
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* xxhash, IRAtom* yyhash,
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* xx,     IRAtom* yy )
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   m64    = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U;
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   syned  = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD32S;
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opOR   = m64 ? Iop_Or64  : Iop_Or32;
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opAND  = m64 ? Iop_And64 : Iop_And32;
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opSHL  = m64 ? Iop_Shl64 : Iop_Shl32;
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opSHR  = m64 ? Iop_Shr64 : Iop_Shr32;
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = m64 ? Ity_I64   : Ity_I32;
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    width  = m64 ? 64        : 32;
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool (*isZero)(IRAtom*) = m64 ? isZeroU64 : isZeroU32;
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* threeLeft1 = NULL;
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* sevenLeft1 = NULL;
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,xxhash));
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,yyhash));
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,xx));
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,yy));
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(xxhash,xx));
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(yyhash,yy));
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cmp_op == Iop_CmpORD32S || cmp_op == Iop_CmpORD32U
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U);
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIROp(cmp_op); VG_(printf)(" ");
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(xx); VG_(printf)(" "); ppIRExpr( yy ); VG_(printf)("\n");
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (syned && isZero(yy)) {
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fancy interpretation */
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* if yy is zero, then it must be fully defined (zero#). */
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isZero(yyhash));
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      threeLeft1 = m64 ? mkU64(3<<1) : mkU32(3<<1);
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            opOR,
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assignNew(
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               'V', mce,ty,
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  opAND,
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkPCastTo(mce,ty, xxhash),
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  threeLeft1
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )),
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assignNew(
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               'V', mce,ty,
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  opSHL,
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assignNew(
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     'V', mce,ty,
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(opSHR, xxhash, mkU8(width-1))),
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU8(3)
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ))
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 );
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* standard interpretation */
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sevenLeft1 = m64 ? mkU64(7<<1) : mkU32(7<<1);
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            opAND,
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkPCastTo( mce,ty,
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkUifU(mce,ty, xxhash,yyhash)),
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sevenLeft1
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Emit a test and complaint if something is undefined. ---*/
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* schemeE ( MCEnv* mce, IRExpr* e ); /* fwds */
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the annotations on a dirty helper to indicate that the stack
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pointer and instruction pointers might be read.  This is the
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   behaviour of all 'emit-a-complaint' style functions we might
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call. */
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di->nFxState = 2;
1110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[0].fx        = Ifx_Read;
1111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[0].offset    = mce->layout->offset_SP;
1112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[0].size      = mce->layout->sizeof_SP;
1113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[0].nRepeats  = 0;
1114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[0].repeatLen = 0;
1115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[1].fx        = Ifx_Read;
1116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[1].offset    = mce->layout->offset_IP;
1117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[1].size      = mce->layout->sizeof_IP;
1118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[1].nRepeats  = 0;
1119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   di->fxState[1].repeatLen = 0;
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Check the supplied *original* |atom| for undefinedness, and emit a
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complaint if so.  Once that happens, mark it as defined.  This is
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possible because the atom is either a tmp or literal.  If it's a
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp, it will be shadowed by a tmp, and so we can set the shadow to
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be defined.  In fact as mentioned above, we will have to allocate a
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new tmp to carry the new 'defined' shadow value, and update the
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   original->tmp mapping accordingly; we cannot simply assign a new
1130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   value to an existing shadow tmp as this breaks SSAness.
1131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   The checks are performed, any resulting complaint emitted, and
1133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   |atom|'s shadow temp set to 'defined', ONLY in the case that
1134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   |guard| evaluates to True at run-time.  If it evaluates to False
1135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   then no action is performed.  If |guard| is NULL (the usual case)
1136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   then it is assumed to be always-true, and hence these actions are
1137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   performed unconditionally.
1138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   This routine does not generate code to check the definedness of
1140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   |guard|.  The caller is assumed to have taken care of that already.
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void complainIfUndefined ( MCEnv* mce, IRAtom* atom, IRExpr *guard )
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  vatom;
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   ty;
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      sz;
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  cond;
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  origin;
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*    fn;
1151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* nm;
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args;
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      nargs;
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Don't do V bit tests if we're not reporting undefined value errors.
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 1)
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (guard)
1160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tl_assert(isOriginalAtom(mce, guard));
1161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Since the original expression is atomic, there's no duplicated
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      work generated by making multiple V-expressions for it.  So we
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      don't really care about the possibility that someone else may
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      also create a V-interpretion for it. */
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, atom));
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vatom = expr2vbits( mce, atom );
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatom));
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom, vatom));
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = typeOfIRExpr(mce->sb->tyenv, vatom);
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sz is only used for constructing the error message */
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cond = mkPCastTo( mce, Ity_I1, vatom );
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* cond will be 0 if all defined, and 1 if any not defined. */
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Get the origin info for the value we are about to check.  At
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      least, if we are doing origin tracking.  If not, use a dummy
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      zero origin. */
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 3) {
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      origin = schemeE( mce, atom );
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mce->hWordTy == Ity_I64) {
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         origin = assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, origin) );
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      origin = NULL;
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fn    = NULL;
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   nm    = NULL;
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   args  = NULL;
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   nargs = -1;
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check0_fail_w_o);
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check0_fail_w_o)";
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1(origin);
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check0_fail_no_o);
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check0_fail_no_o)";
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_0();
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 0;
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check1_fail_w_o);
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check1_fail_w_o)";
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1(origin);
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check1_fail_no_o);
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check1_fail_no_o)";
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_0();
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 0;
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check4_fail_w_o);
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check4_fail_w_o)";
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1(origin);
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check4_fail_no_o);
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check4_fail_no_o)";
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_0();
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 0;
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check8_fail_w_o);
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check8_fail_w_o)";
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1(origin);
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check8_fail_no_o);
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check8_fail_no_o)";
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_0();
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 0;
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 16:
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_checkN_fail_w_o);
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_checkN_fail_w_o)";
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_2( mkIRExpr_HWord( sz ), origin);
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 2;
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_checkN_fail_no_o);
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_checkN_fail_no_o)";
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1( mkIRExpr_HWord( sz ) );
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("unexpected szB");
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(fn);
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(nm);
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(args);
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(nargs >= 0 && nargs <= 2);
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( (MC_(clo_mc_level) == 3 && origin != NULL)
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || (MC_(clo_mc_level) == 2 && origin == NULL) );
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_0_N( nargs/*regparms*/, nm,
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           VG_(fnptr_to_fnentry)( fn ), args );
1276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   di->guard = cond; // and cond is PCast-to-1(atom#)
1277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* If the complaint is to be issued under a guard condition, AND
1279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      that into the guard condition for the helper call. */
1280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (guard) {
1281436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom *g1 = assignNew('V', mce, Ity_I32, unop(Iop_1Uto32, di->guard));
1282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom *g2 = assignNew('V', mce, Ity_I32, unop(Iop_1Uto32, guard));
1283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom *e  = assignNew('V', mce, Ity_I32, binop(Iop_And32, g1, g2));
1284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      di->guard  = assignNew('V', mce, Ity_I1,  unop(Iop_32to1, e));
1285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setHelperAnns( mce, di );
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'V', mce, IRStmt_Dirty(di));
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* If |atom| is shadowed by an IRTemp, set the shadow tmp to be
1291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      defined -- but only in the case where the guard evaluates to
1292436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      True at run-time.  Do the update by setting the orig->shadow
1293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      mapping for tmp to reflect the fact that this shadow is getting
1294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      a new value. */
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(vatom));
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sameKindedAtoms ... */
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vatom->tag == Iex_RdTmp) {
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(atom->tag == Iex_RdTmp);
1299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (guard == NULL) {
1300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         // guard is 'always True', hence update unconditionally
1301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         newShadowTmpV(mce, atom->Iex.RdTmp.tmp);
1302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         assign('V', mce, findShadowTmpV(mce, atom->Iex.RdTmp.tmp),
1303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          definedOfType(ty));
1304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      } else {
1305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         // update the temp only conditionally.  Do this by copying
1306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         // its old value when the guard is False.
1307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         // The old value ..
1308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRTemp old_tmpV = findShadowTmpV(mce, atom->Iex.RdTmp.tmp);
1309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         newShadowTmpV(mce, atom->Iex.RdTmp.tmp);
1310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRAtom* new_tmpV
1311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            = assignNew('V', mce, shadowTypeV(ty),
1312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        IRExpr_ITE(guard, definedOfType(ty),
1313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                          mkexpr(old_tmpV)));
1314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         assign('V', mce, findShadowTmpV(mce, atom->Iex.RdTmp.tmp), new_tmpV);
1315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Shadowing PUTs/GETs, and indexed variants thereof    ---*/
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Examine the always-defined sections declared in layout to see if
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the (offset,size) section is within one.  Note, is is an error to
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   partially fall into such a region: (offset,size) should either be
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   completely in such a region or completely not-in such a region.
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int minoffD, maxoffD, i;
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int minoff = offset;
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int maxoff = minoff + size - 1;
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert((minoff & ~0xFFFF) == 0);
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert((maxoff & ~0xFFFF) == 0);
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      minoffD = mce->layout->alwaysDefd[i].offset;
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert((minoffD & ~0xFFFF) == 0);
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert((maxoffD & ~0xFFFF) == 0);
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (maxoff < minoffD || maxoffD < minoff)
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue; /* no overlap */
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (minoff >= minoffD && maxoff <= maxoffD)
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True; /* completely contained in an always-defd section */
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False; /* could not find any containing section */
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate into bb suitable actions to shadow this Put.  If the state
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   slice is marked 'always defined', do nothing.  Otherwise, write the
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   supplied V bits to the shadow state.  We can pass in either an
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   original atom or a V-atom, but not both.  In the former case the
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   relevant V-bits are then generated from the original.
1359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   We assume here, that the definedness of GUARD has already been checked.
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_shadow_PUT ( MCEnv* mce,  Int offset,
1363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     IRAtom* atom, IRAtom* vatom, IRExpr *guard )
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty;
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Don't do shadow PUTs if we're not doing undefined value checking.
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Their absence lets Vex's optimiser remove all the shadow computation
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // that they depend on, which includes GETs of the shadow registers.
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 1)
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (atom) {
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(!vatom);
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, atom));
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vatom = expr2vbits( mce, atom );
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(vatom);
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, vatom));
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = typeOfIRExpr(mce->sb->tyenv, vatom);
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ty != Ity_I1);
1384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(ty != Ity_I128);
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* later: no ... */
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* emit code to emit a complaint if any of the vbits are 1. */
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* complainIfUndefined(mce, atom); */
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Do a plain shadow Put. */
1391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (guard) {
1392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* If the guard expression evaluates to false we simply Put the value
1393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            that is already stored in the guest state slot */
1394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRAtom *cond, *iffalse;
1395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         cond    = assignNew('V', mce, Ity_I1, guard);
1397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iffalse = assignNew('V', mce, ty,
1398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             IRExpr_Get(offset + mce->layout->total_sizeB, ty));
1399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vatom   = assignNew('V', mce, ty, IRExpr_ITE(cond, vatom, iffalse));
1400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( 'V', mce, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ));
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an expression which contains the V bits corresponding to the
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given GETI (passed in in pieces).
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid do_shadow_PUTI ( MCEnv* mce, IRPutI *puti)
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty, tyS;
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     arrSize;;
1415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRRegArray* descr = puti->descr;
1416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRAtom*     ix    = puti->ix;
1417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int         bias  = puti->bias;
1418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRAtom*     atom  = puti->data;
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Don't do shadow PUTIs if we're not doing undefined value checking.
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Their absence lets Vex's optimiser remove all the shadow computation
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // that they depend on, which includes GETIs of the shadow registers.
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 1)
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom));
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vatom = expr2vbits( mce, atom );
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom, vatom));
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty   = descr->elemTy;
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tyS  = shadowTypeV(ty);
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arrSize = descr->nElems * sizeofIRType(ty);
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ty != Ity_I1);
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,ix));
1434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   complainIfUndefined(mce, ix, NULL);
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isAlwaysDefd(mce, descr->base, arrSize)) {
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* later: no ... */
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* emit code to emit a complaint if any of the vbits are 1. */
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* complainIfUndefined(mce, atom); */
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Do a cloned version of the Put that refers to the shadow
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         area. */
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRRegArray* new_descr
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkIRRegArray( descr->base + mce->layout->total_sizeB,
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         tyS, descr->nElems);
1445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( 'V', mce, IRStmt_PutI( mkIRPutI(new_descr, ix, bias, vatom) ));
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an expression which contains the V bits corresponding to the
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given GET (passed in in pieces).
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType tyS = shadowTypeV(ty);
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ty != Ity_I1);
1458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(ty != Ity_I128);
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Always defined, return all zeroes of the relevant type */
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return definedOfType(tyS);
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* return a cloned version of the Get that refers to the shadow
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         area. */
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FIXME: this isn't an atom! */
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an expression which contains the V bits corresponding to the
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given GETI (passed in in pieces).
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* shadow_GETI ( MCEnv* mce,
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRRegArray* descr, IRAtom* ix, Int bias )
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty   = descr->elemTy;
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType tyS  = shadowTypeV(ty);
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int arrSize = descr->nElems * sizeofIRType(ty);
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ty != Ity_I1);
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,ix));
1483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   complainIfUndefined(mce, ix, NULL);
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isAlwaysDefd(mce, descr->base, arrSize)) {
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Always defined, return all zeroes of the relevant type */
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return definedOfType(tyS);
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* return a cloned version of the Get that refers to the shadow
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         area. */
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRRegArray* new_descr
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkIRRegArray( descr->base + mce->layout->total_sizeB,
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         tyS, descr->nElems);
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_GetI( new_descr, ix, bias );
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Generating approximations for unknown operations,    ---*/
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- using lazy-propagate semantics                       ---*/
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Lazy propagation of undefinedness from two values, resulting in the
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   specified shadow type.
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t1 = typeOfIRExpr(mce->sb->tyenv, va1);
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t2 = typeOfIRExpr(mce->sb->tyenv, va2);
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va1));
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va2));
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The general case is inefficient because PCast is an expensive
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      operation.  Here are some special cases which use PCast only
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      once rather than twice. */
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I64 x I64 -> I64 */
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I64) {
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy2: I64 x I64 -> I64\n");
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, va1, va2);
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, at);
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I64 x I64 -> I32 */
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I32) {
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy2: I64 x I64 -> I32\n");
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, va1, va2);
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I32, at);
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("mkLazy2 ");
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t1);
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("_");
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t2);
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("_");
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(finalVty);
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* General case: force everything via 32-bit intermediaries. */
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I32, va1);
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, finalVty, at);
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 3-arg version of the above. */
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* mkLazy3 ( MCEnv* mce, IRType finalVty,
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRAtom* va1, IRAtom* va2, IRAtom* va3 )
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t1 = typeOfIRExpr(mce->sb->tyenv, va1);
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t2 = typeOfIRExpr(mce->sb->tyenv, va2);
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t3 = typeOfIRExpr(mce->sb->tyenv, va3);
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va1));
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va2));
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va3));
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The general case is inefficient because PCast is an expensive
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      operation.  Here are some special cases which use PCast only
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      twice rather than three times. */
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I32 x I64 x I64 -> I64 */
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Standard FP idiom: rm x FParg1 x FParg2 -> FPresult */
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && finalVty == Ity_I64) {
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy3: I32 x I64 x I64 -> I64\n");
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Widen 1st arg to I64.  Since 1st arg is typically a rounding
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mode indication which is fully defined, this should get
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         folded out later. */
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, va1);
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now fold in 2nd and 3rd args. */
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va2);
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va3);
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* and PCast once again. */
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, at);
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* I32 x I8 x I64 -> I64 */
1588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (t1 == Ity_I32 && t2 == Ity_I8 && t3 == Ity_I64
1589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       && finalVty == Ity_I64) {
1590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (0) VG_(printf)("mkLazy3: I32 x I8 x I64 -> I64\n");
1591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Widen 1st and 2nd args to I64.  Since 1st arg is typically a
1592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       * rounding mode indication which is fully defined, this should
1593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       * get folded out later.
1594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      */
1595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom* at1 = mkPCastTo(mce, Ity_I64, va1);
1596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom* at2 = mkPCastTo(mce, Ity_I64, va2);
1597436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      at = mkUifU(mce, Ity_I64, at1, at2);  // UifU(PCast(va1), PCast(va2))
1598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      at = mkUifU(mce, Ity_I64, at, va3);
1599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* and PCast once again. */
1600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      at = mkPCastTo(mce, Ity_I64, at);
1601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return at;
1602436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1603436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I32 x I64 x I64 -> I32 */
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && finalVty == Ity_I32) {
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy3: I32 x I64 x I64 -> I32\n");
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, va1);
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va2);
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va3);
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I32, at);
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I32 x I32 x I32 -> I32 */
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32-bit FP idiom, as (eg) happens on ARM */
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I32 && t2 == Ity_I32 && t3 == Ity_I32
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && finalVty == Ity_I32) {
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy3: I32 x I32 x I32 -> I32\n");
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = va1;
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I32, at, va2);
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I32, at, va3);
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I32, at);
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* I32 x I128 x I128 -> I128 */
1628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Standard FP idiom: rm x FParg1 x FParg2 -> FPresult */
1629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (t1 == Ity_I32 && t2 == Ity_I128 && t3 == Ity_I128
1630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && finalVty == Ity_I128) {
1631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0) VG_(printf)("mkLazy3: I32 x I128 x I128 -> I128\n");
1632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Widen 1st arg to I128.  Since 1st arg is typically a rounding
1633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mode indication which is fully defined, this should get
1634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         folded out later. */
1635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkPCastTo(mce, Ity_I128, va1);
1636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Now fold in 2nd and 3rd args. */
1637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I128, at, va2);
1638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I128, at, va3);
1639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* and PCast once again. */
1640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkPCastTo(mce, Ity_I128, at);
1641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return at;
1642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* I32 x I8 x I128 -> I128 */
1645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Standard FP idiom: rm x FParg1 x FParg2 -> FPresult */
1646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (t1 == Ity_I32 && t2 == Ity_I8 && t3 == Ity_I128
1647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       && finalVty == Ity_I128) {
1648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (0) VG_(printf)("mkLazy3: I32 x I8 x I128 -> I128\n");
1649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Use I64 as an intermediate type, which means PCasting all 3
1650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         args to I64 to start with. 1st arg is typically a rounding
1651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         mode indication which is fully defined, so we hope that it
1652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         will get folded out later. */
1653436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom* at1 = mkPCastTo(mce, Ity_I64, va1);
1654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom* at2 = mkPCastTo(mce, Ity_I64, va2);
1655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom* at3 = mkPCastTo(mce, Ity_I64, va3);
1656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Now UifU all three together. */
1657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      at = mkUifU(mce, Ity_I64, at1, at2);  // UifU(PCast(va1), PCast(va2))
1658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      at = mkUifU(mce, Ity_I64, at, at3);   // ... `UifU` PCast(va3)
1659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* and PCast once again. */
1660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      at = mkPCastTo(mce, Ity_I128, at);
1661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return at;
1662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (1) {
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("mkLazy3: ");
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t1);
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t2);
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t3);
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" -> ");
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(finalVty);
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0);
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* General case: force everything via 32-bit intermediaries. */
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I32, va1);
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va3));
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, finalVty, at);
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 4-arg version of the above. */
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* mkLazy4 ( MCEnv* mce, IRType finalVty,
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRAtom* va1, IRAtom* va2, IRAtom* va3, IRAtom* va4 )
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t1 = typeOfIRExpr(mce->sb->tyenv, va1);
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t2 = typeOfIRExpr(mce->sb->tyenv, va2);
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t3 = typeOfIRExpr(mce->sb->tyenv, va3);
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t4 = typeOfIRExpr(mce->sb->tyenv, va4);
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va1));
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va2));
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va3));
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va4));
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The general case is inefficient because PCast is an expensive
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      operation.  Here are some special cases which use PCast only
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      twice rather than three times. */
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I32 x I64 x I64 x I64 -> I64 */
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Standard FP idiom: rm x FParg1 x FParg2 x FParg3 -> FPresult */
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64 && t4 == Ity_I64
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && finalVty == Ity_I64) {
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy4: I32 x I64 x I64 x I64 -> I64\n");
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Widen 1st arg to I64.  Since 1st arg is typically a rounding
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mode indication which is fully defined, this should get
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         folded out later. */
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, va1);
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now fold in 2nd, 3rd, 4th args. */
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va2);
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va3);
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va4);
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* and PCast once again. */
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, at);
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* I32 x I32 x I32 x I32 -> I32 */
1724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Standard FP idiom: rm x FParg1 x FParg2 x FParg3 -> FPresult */
1725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (t1 == Ity_I32 && t2 == Ity_I32 && t3 == Ity_I32 && t4 == Ity_I32
1726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && finalVty == Ity_I32) {
1727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0) VG_(printf)("mkLazy4: I32 x I32 x I32 x I32 -> I32\n");
1728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = va1;
1729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Now fold in 2nd, 3rd, 4th args. */
1730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I32, at, va2);
1731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I32, at, va3);
1732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I32, at, va4);
1733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkPCastTo(mce, Ity_I32, at);
1734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return at;
1735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (1) {
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("mkLazy4: ");
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t1);
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t2);
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t3);
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t4);
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" -> ");
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(finalVty);
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0);
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do the lazy propagation game from a null-terminated vector of
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   atoms.  This is presumably the arguments to a helper call, so the
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCallee info is also supplied in order that we can know which
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arguments should be ignored (via the .mcx_mask field).
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* mkLazyN ( MCEnv* mce,
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* here;
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* curr;
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  mergeTy;
1768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool    mergeTy64 = True;
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Decide on the type of the merge intermediary.  If all relevant
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      args are I64, then it's I64.  In all other circumstances, use
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      I32. */
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; exprvec[i]; i++) {
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(i < 32);
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, exprvec[i]));
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cee->mcx_mask & (1<<i))
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (typeOfIRExpr(mce->sb->tyenv, exprvec[i]) != Ity_I64)
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mergeTy64 = False;
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mergeTy = mergeTy64  ? Ity_I64  : Ity_I32;
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   curr    = definedOfType(mergeTy);
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; exprvec[i]; i++) {
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(i < 32);
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, exprvec[i]));
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Only take notice of this arg if the callee's mc-exclusion
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask does not say it is to be excluded. */
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cee->mcx_mask & (1<<i)) {
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* the arg is to be excluded from definedness checking.  Do
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nothing. */
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* calculate the arg's definedness, and pessimistically merge
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            it in. */
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = mkPCastTo( mce, mergeTy, expr2vbits(mce, exprvec[i]) );
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = mergeTy64
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ? mkUifU64(mce, here, curr)
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   : mkUifU32(mce, here, curr);
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkPCastTo(mce, finalVtype, curr );
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Generating expensive sequences for exact carry-chain ---*/
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- propagation in add/sub and related operations.       ---*/
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expensiveAddSub ( MCEnv*  mce,
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Bool    add,
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRType  ty,
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* qaa, IRAtom* qbb,
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* aa,  IRAtom* bb )
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *a_min, *b_min, *a_max, *b_max;
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opAND, opOR, opXOR, opNOT, opADD, opSUB;
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,qaa));
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,qbb));
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,aa));
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,bb));
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(qaa,aa));
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(qbb,bb));
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opAND = Iop_And32;
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opOR  = Iop_Or32;
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opXOR = Iop_Xor32;
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opNOT = Iop_Not32;
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opADD = Iop_Add32;
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opSUB = Iop_Sub32;
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opAND = Iop_And64;
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opOR  = Iop_Or64;
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opXOR = Iop_Xor64;
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opNOT = Iop_Not64;
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opADD = Iop_Add64;
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opSUB = Iop_Sub64;
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("expensiveAddSub");
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // a_min = aa & ~qaa
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a_min = assignNew('V', mce,ty,
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(opAND, aa,
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  assignNew('V', mce,ty, unop(opNOT, qaa))));
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // b_min = bb & ~qbb
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   b_min = assignNew('V', mce,ty,
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(opAND, bb,
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  assignNew('V', mce,ty, unop(opNOT, qbb))));
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // a_max = aa | qaa
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a_max = assignNew('V', mce,ty, binop(opOR, aa, qaa));
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // b_max = bb | qbb
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   b_max = assignNew('V', mce,ty, binop(opOR, bb, qbb));
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (add) {
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignNew('V', mce,ty,
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop( opOR,
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                assignNew('V', mce,ty, binop(opOR, qaa, qbb)),
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                assignNew('V', mce,ty,
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( opXOR,
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          assignNew('V', mce,ty, binop(opADD, a_min, b_min)),
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          assignNew('V', mce,ty, binop(opADD, a_max, b_max))
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                )
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // result = (qaa | qbb) | ((a_min - b_max) ^ (a_max + b_min))
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignNew('V', mce,ty,
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop( opOR,
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                assignNew('V', mce,ty, binop(opOR, qaa, qbb)),
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                assignNew('V', mce,ty,
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( opXOR,
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          assignNew('V', mce,ty, binop(opSUB, a_min, b_max)),
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          assignNew('V', mce,ty, binop(opSUB, a_max, b_min))
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                )
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1899436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
1900436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* expensiveCountTrailingZeroes ( MCEnv* mce, IROp czop,
1901436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       IRAtom* atom, IRAtom* vatom )
1902436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
1903436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRType ty;
1904436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IROp xorOp, subOp, andOp;
1905436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRExpr *one;
1906436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom *improver, *improved;
1907436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(isShadowAtom(mce,vatom));
1908436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(isOriginalAtom(mce,atom));
1909436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(sameKindedAtoms(atom,vatom));
1910436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (czop) {
1912436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Ctz32:
1913436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ty = Ity_I32;
1914436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         xorOp = Iop_Xor32;
1915436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         subOp = Iop_Sub32;
1916436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         andOp = Iop_And32;
1917436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         one = mkU32(1);
1918436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
1919436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Ctz64:
1920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ty = Ity_I64;
1921436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         xorOp = Iop_Xor64;
1922436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         subOp = Iop_Sub64;
1923436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         andOp = Iop_And64;
1924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         one = mkU64(1);
1925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
1926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
1927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ppIROp(czop);
1928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(tool_panic)("memcheck:expensiveCountTrailingZeroes");
1929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1930436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // improver = atom ^ (atom - 1)
1932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //
1933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // That is, improver has its low ctz(atom) bits equal to one;
1934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // higher bits (if any) equal to zero.
1935436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   improver = assignNew('V', mce,ty,
1936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        binop(xorOp,
1937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              atom,
1938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              assignNew('V', mce, ty,
1939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        binop(subOp, atom, one))));
1940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // improved = vatom & improver
1942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //
1943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // That is, treat any V bits above the first ctz(atom) bits as
1944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // "defined".
1945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   improved = assignNew('V', mce, ty,
1946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        binop(andOp, vatom, improver));
1947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // Return pessimizing cast of improved.
1949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return mkPCastTo(mce, ty, improved);
1950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Scalar shifts.                                       ---*/
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce an interpretation for (aa << bb) (or >>s, >>u).  The basic
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   idea is to shift the definedness bits by the original shift amount.
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This introduces 0s ("defined") in new positions for left shifts and
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned right shifts, and copies the top definedness bit for
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   signed right shifts.  So, conveniently, applying the original shift
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   operator to the definedness bits for the left arg is exactly the
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   right thing to do:
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (qaa << bb)
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   However if the shift amount is undefined then the whole result
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is undefined.  Hence need:
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (qaa << bb) `UifU` PCast(qbb)
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If the shift amount bb is a literal than qbb will say 'all defined'
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and the UifU and PCast will get folded out by post-instrumentation
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimisation.
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* scalarShift ( MCEnv*  mce,
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRType  ty,
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IROp    original_op,
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* qaa, IRAtom* qbb,
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* aa,  IRAtom* bb )
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,qaa));
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,qbb));
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,aa));
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,bb));
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(qaa,aa));
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(qbb,bb));
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignNew(
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         'V', mce, ty,
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkUifU( mce, ty,
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 assignNew('V', mce, ty, binop(original_op, qaa, bb)),
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkPCastTo(mce, ty, qbb)
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for dealing with vector primops.             ---*/
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vector pessimisation -- pessimise within each lane individually. */
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRAtom* mkPCast64x4 ( MCEnv* mce, IRAtom* at )
2026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return assignNew('V', mce, Ity_V256, unop(Iop_CmpNEZ64x4, at));
2028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic IRAtom* mkPCast32x8 ( MCEnv* mce, IRAtom* at )
2031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return assignNew('V', mce, Ity_V256, unop(Iop_CmpNEZ32x8, at));
2033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast32x2 ( MCEnv* mce, IRAtom* at )
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, unop(Iop_CmpNEZ32x2, at));
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2040436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic IRAtom* mkPCast16x16 ( MCEnv* mce, IRAtom* at )
2041436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2042436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return assignNew('V', mce, Ity_V256, unop(Iop_CmpNEZ16x16, at));
2043436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2044436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast16x4 ( MCEnv* mce, IRAtom* at )
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, unop(Iop_CmpNEZ16x4, at));
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2050436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic IRAtom* mkPCast8x32 ( MCEnv* mce, IRAtom* at )
2051436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2052436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return assignNew('V', mce, Ity_V256, unop(Iop_CmpNEZ8x32, at));
2053436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2054436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast8x8 ( MCEnv* mce, IRAtom* at )
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, unop(Iop_CmpNEZ8x8, at));
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast16x2 ( MCEnv* mce, IRAtom* at )
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, unop(Iop_CmpNEZ16x2, at));
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast8x4 ( MCEnv* mce, IRAtom* at )
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, unop(Iop_CmpNEZ8x4, at));
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Here's a simple scheme capable of handling ops derived from SSE1
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code and while only generating ops that can be efficiently
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   implemented in SSE1. */
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* All-lanes versions are straightforward:
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   binary32Fx4(x,y)   ==> PCast32x4(UifUV128(x#,y#))
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unary32Fx4(x,y)    ==> PCast32x4(x#)
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Lowest-lane-only versions are more complex:
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   binary32F0x4(x,y)  ==> SetV128lo32(
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             x#,
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             PCast32(V128to32(UifUV128(x#,y#)))
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          )
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is perhaps not so obvious.  In particular, it's faster to
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do a V128-bit UifU and then take the bottom 32 bits than the more
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   obvious scheme of taking the bottom 32 bits of each operand
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and doing a 32-bit UifU.  Basically since UifU is fast and
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   chopping lanes off vector values is slow.
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Finally:
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unary32F0x4(x)     ==> SetV128lo32(
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             x#,
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             PCast32(V128to32(x#))
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          )
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Where:
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PCast32(v#)   = 1Sto32(CmpNE32(v#,0))
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PCast32x4(v#) = CmpNEZ32x4(v#)
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatomX, vatomY);
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, mkPCast32x4(mce, at));
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, mkPCast32x4(mce, vatomX));
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatomX, vatomY);
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I32, unop(Iop_V128to32, at));
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I32, at);
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I32, unop(Iop_V128to32, vatomX));
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I32, at);
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- ... and ... 64Fx2 versions of the same ... --- */
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatomX, vatomY);
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, mkPCast64x2(mce, at));
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, mkPCast64x2(mce, vatomX));
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatomX, vatomY);
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, at));
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I64, at);
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, vatomX));
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I64, at);
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- --- ... and ... 32Fx2 versions of the same --- --- */
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatomX, vatomY);
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I64, mkPCast32x2(mce, at));
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary32Fx2 ( MCEnv* mce, IRAtom* vatomX )
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I64, mkPCast32x2(mce, vatomX));
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* --- ... and ... 64Fx4 versions of the same ... --- */
2220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
2222663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengIRAtom* binary64Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
2223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRAtom* at;
2225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce, vatomX));
2226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce, vatomY));
2227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   at = mkUifUV256(mce, vatomX, vatomY);
2228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   at = assignNew('V', mce, Ity_V256, mkPCast64x4(mce, at));
2229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return at;
2230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
2233663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengIRAtom* unary64Fx4 ( MCEnv* mce, IRAtom* vatomX )
2234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRAtom* at;
2236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce, vatomX));
2237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   at = assignNew('V', mce, Ity_V256, mkPCast64x4(mce, vatomX));
2238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return at;
2239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* --- ... and ... 32Fx8 versions of the same ... --- */
2242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
2244663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengIRAtom* binary32Fx8 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
2245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRAtom* at;
2247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce, vatomX));
2248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce, vatomY));
2249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   at = mkUifUV256(mce, vatomX, vatomY);
2250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   at = assignNew('V', mce, Ity_V256, mkPCast32x8(mce, at));
2251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return at;
2252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
2255663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengIRAtom* unary32Fx8 ( MCEnv* mce, IRAtom* vatomX )
2256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRAtom* at;
2258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(isShadowAtom(mce, vatomX));
2259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   at = assignNew('V', mce, Ity_V256, mkPCast32x8(mce, vatomX));
2260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return at;
2261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* --- 64Fx2 binary FP ops, with rounding mode --- */
2264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
2266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* binary64Fx2_w_rm ( MCEnv* mce, IRAtom* vRM,
2267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       IRAtom* vatomX, IRAtom* vatomY )
2268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* This is the same as binary64Fx2, except that we subsequently
2270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      pessimise vRM (definedness of the rounding mode), widen to 128
2271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      bits and UifU it into the result.  As with the scalar cases, if
2272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      the RM is a constant then it is defined and so this extra bit
2273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      will get constant-folded out later. */
2274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // "do" the vector args
2275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* t1 = binary64Fx2(mce, vatomX, vatomY);
2276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // PCast the RM, and widen it to 128 bits
2277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* t2 = mkPCastTo(mce, Ity_V128, vRM);
2278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // Roll it into the result
2279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   t1 = mkUifUV128(mce, t1, t2);
2280436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return t1;
2281436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* --- ... and ... 32Fx4 versions of the same --- */
2284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
2286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* binary32Fx4_w_rm ( MCEnv* mce, IRAtom* vRM,
2287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       IRAtom* vatomX, IRAtom* vatomY )
2288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* t1 = binary32Fx4(mce, vatomX, vatomY);
2290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // PCast the RM, and widen it to 128 bits
2291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* t2 = mkPCastTo(mce, Ity_V128, vRM);
2292436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // Roll it into the result
2293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   t1 = mkUifUV128(mce, t1, t2);
2294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return t1;
2295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2297436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* --- ... and ... 64Fx4 versions of the same --- */
2298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
2300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* binary64Fx4_w_rm ( MCEnv* mce, IRAtom* vRM,
2301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       IRAtom* vatomX, IRAtom* vatomY )
2302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* t1 = binary64Fx4(mce, vatomX, vatomY);
2304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // PCast the RM, and widen it to 256 bits
2305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* t2 = mkPCastTo(mce, Ity_V256, vRM);
2306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // Roll it into the result
2307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   t1 = mkUifUV256(mce, t1, t2);
2308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return t1;
2309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* --- ... and ... 32Fx8 versions of the same --- */
2312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
2314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* binary32Fx8_w_rm ( MCEnv* mce, IRAtom* vRM,
2315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       IRAtom* vatomX, IRAtom* vatomY )
2316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* t1 = binary32Fx8(mce, vatomX, vatomY);
2318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // PCast the RM, and widen it to 256 bits
2319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* t2 = mkPCastTo(mce, Ity_V256, vRM);
2320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // Roll it into the result
2321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   t1 = mkUifUV256(mce, t1, t2);
2322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return t1;
2323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- --- Vector saturated narrowing --- --- */
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* We used to do something very clever here, but on closer inspection
2329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (2011-Jun-15), and in particular bug #279698, it turns out to be
2330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   wrong.  Part of the problem came from the fact that for a long
2331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   time, the IR primops to do with saturated narrowing were
2332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   underspecified and managed to confuse multiple cases which needed
2333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to be separate: the op names had a signedness qualifier, but in
2334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fact the source and destination signednesses needed to be specified
2335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   independently, so the op names really need two independent
2336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   signedness specifiers.
2337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   As of 2011-Jun-15 (ish) the underspecification was sorted out
2339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   properly.  The incorrect instrumentation remained, though.  That
2340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   has now (2011-Oct-22) been fixed.
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   What we now do is simple:
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Let the original narrowing op be QNarrowBinXtoYxZ, where Z is a
2345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   number of lanes, X is the source lane width and signedness, and Y
2346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   is the destination lane width and signedness.  In all cases the
2347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   destination lane width is half the source lane width, so the names
2348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   have a bit of redundancy, but are at least easy to read.
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   For example, Iop_QNarrowBin32Sto16Ux8 narrows 8 lanes of signed 32s
2351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to unsigned 16s.
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Let Vanilla(OP) be a function that takes OP, one of these
2354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   saturating narrowing ops, and produces the same "shaped" narrowing
2355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   op which is not saturating, but merely dumps the most significant
2356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   bits.  "same shape" means that the lane numbers and widths are the
2357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   same as with OP.
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   For example, Vanilla(Iop_QNarrowBin32Sto16Ux8)
2360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  = Iop_NarrowBin32to16x8,
2361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   that is, narrow 8 lanes of 32 bits to 8 lanes of 16 bits, by
2362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   dumping the top half of each lane.
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   So, with that in place, the scheme is simple, and it is simple to
2365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pessimise each lane individually and then apply Vanilla(OP) so as
2366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to get the result in the right "shape".  If the original OP is
2367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   QNarrowBinXtoYxZ then we produce
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Vanilla(OP)( PCast-X-to-X-x-Z(vatom1), PCast-X-to-X-x-Z(vatom2) )
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   or for the case when OP is unary (Iop_QNarrowUn*)
2372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Vanilla(OP)( PCast-X-to-X-x-Z(vatom) )
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIROp vanillaNarrowingOpOfShape ( IROp qnarrowOp )
2377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (qnarrowOp) {
2379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Binary: (128, 128) -> 128 */
2380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux16:
2381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16:
2382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Uto8Ux16:
2383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QNarrowBin64Sto32Sx4:
2384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QNarrowBin64Uto32Ux4:
2385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowBin16to8x16;
2386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Ux8:
2387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8:
2388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Uto16Ux8:
2389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowBin32to16x8;
2390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Binary: (64, 64) -> 64 */
2391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx4:
2392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowBin32to16x4;
2393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux8:
2394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx8:
2395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowBin16to8x8;
2396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Unary: 128 -> 64 */
2397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Uto32Ux2:
2398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Sx2:
2399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Ux2:
2400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowUn64to32x2;
2401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Uto16Ux4:
2402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Sx4:
2403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Ux4:
2404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowUn32to16x4;
2405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Uto8Ux8:
2406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Sx8:
2407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Ux8:
2408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowUn16to8x8;
2409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
2410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ppIROp(qnarrowOp);
2411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(tool_panic)("vanillaNarrowOpOfShape");
2412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
2416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRAtom* vectorNarrowBinV128 ( MCEnv* mce, IROp narrow_op,
2417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              IRAtom* vatom1, IRAtom* vatom2)
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *at1, *at2, *at3;
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*pcast)( MCEnv*, IRAtom* );
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (narrow_op) {
2422436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QNarrowBin64Sto32Sx4: pcast = mkPCast32x4; break;
2423436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QNarrowBin64Uto32Ux4: pcast = mkPCast32x4; break;
2424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8: pcast = mkPCast32x4; break;
2425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Uto16Ux8: pcast = mkPCast32x4; break;
2426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Ux8: pcast = mkPCast32x4; break;
2427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16: pcast = mkPCast16x8; break;
2428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Uto8Ux16: pcast = mkPCast16x8; break;
2429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux16: pcast = mkPCast16x8; break;
2430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: VG_(tool_panic)("vectorNarrowBinV128");
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IROp vanilla_narrow = vanillaNarrowingOpOfShape(narrow_op);
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at1 = assignNew('V', mce, Ity_V128, pcast(mce, vatom1));
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at2 = assignNew('V', mce, Ity_V128, pcast(mce, vatom2));
2437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   at3 = assignNew('V', mce, Ity_V128, binop(vanilla_narrow, at1, at2));
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at3;
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRAtom* vectorNarrowBin64 ( MCEnv* mce, IROp narrow_op,
2443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            IRAtom* vatom1, IRAtom* vatom2)
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *at1, *at2, *at3;
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*pcast)( MCEnv*, IRAtom* );
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (narrow_op) {
2448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx4: pcast = mkPCast32x2; break;
2449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx8:  pcast = mkPCast16x4; break;
2450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux8:  pcast = mkPCast16x4; break;
2451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: VG_(tool_panic)("vectorNarrowBin64");
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IROp vanilla_narrow = vanillaNarrowingOpOfShape(narrow_op);
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at1 = assignNew('V', mce, Ity_I64, pcast(mce, vatom1));
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at2 = assignNew('V', mce, Ity_I64, pcast(mce, vatom2));
2458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   at3 = assignNew('V', mce, Ity_I64, binop(vanilla_narrow, at1, at2));
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at3;
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRAtom* vectorNarrowUnV128 ( MCEnv* mce, IROp narrow_op,
2464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             IRAtom* vatom1)
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *at1, *at2;
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*pcast)( MCEnv*, IRAtom* );
24689bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root   tl_assert(isShadowAtom(mce,vatom1));
2469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* For vanilla narrowing (non-saturating), we can just apply
2470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      the op directly to the V bits. */
2471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (narrow_op) {
2472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn16to8x8:
2473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn32to16x4:
2474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn64to32x2:
2475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         at1 = assignNew('V', mce, Ity_I64, unop(narrow_op, vatom1));
2476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return at1;
2477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
2478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break; /* Do Plan B */
2479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Plan B: for ops that involve a saturation operation on the args,
2481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      we must PCast before the vanilla narrow. */
2482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (narrow_op) {
2483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Sx8:  pcast = mkPCast16x8; break;
2484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Ux8:  pcast = mkPCast16x8; break;
2485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Uto8Ux8:  pcast = mkPCast16x8; break;
2486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Sx4: pcast = mkPCast32x4; break;
2487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Ux4: pcast = mkPCast32x4; break;
2488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Uto16Ux4: pcast = mkPCast32x4; break;
2489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Sx2: pcast = mkPCast64x2; break;
2490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Ux2: pcast = mkPCast64x2; break;
2491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Uto32Ux2: pcast = mkPCast64x2; break;
2492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: VG_(tool_panic)("vectorNarrowUnV128");
2493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IROp vanilla_narrow = vanillaNarrowingOpOfShape(narrow_op);
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at1 = assignNew('V', mce, Ity_V128, pcast(mce, vatom1));
2496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   at2 = assignNew('V', mce, Ity_I64, unop(vanilla_narrow, at1));
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at2;
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRAtom* vectorWidenI64 ( MCEnv* mce, IROp longen_op,
2502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         IRAtom* vatom1)
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *at1, *at2;
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*pcast)( MCEnv*, IRAtom* );
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (longen_op) {
2507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen8Uto16x8:  pcast = mkPCast16x8; break;
2508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen8Sto16x8:  pcast = mkPCast16x8; break;
2509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen16Uto32x4: pcast = mkPCast32x4; break;
2510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen16Sto32x4: pcast = mkPCast32x4; break;
2511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen32Uto64x2: pcast = mkPCast64x2; break;
2512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen32Sto64x2: pcast = mkPCast64x2; break;
2513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: VG_(tool_panic)("vectorWidenI64");
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at1 = assignNew('V', mce, Ity_V128, unop(longen_op, vatom1));
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at2 = assignNew('V', mce, Ity_V128, pcast(mce, at1));
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at2;
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- --- Vector integer arithmetic --- --- */
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Simple ... UifU the args and per-lane pessimise the results. */
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* --- V256-bit versions --- */
2527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
2529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* binary8Ix32 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* at;
2532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   at = mkUifUV256(mce, vatom1, vatom2);
2533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   at = mkPCast8x32(mce, at);
2534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return at;
2535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
2538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* binary16Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* at;
2541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   at = mkUifUV256(mce, vatom1, vatom2);
2542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   at = mkPCast16x16(mce, at);
2543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return at;
2544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
2547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* binary32Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* at;
2550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   at = mkUifUV256(mce, vatom1, vatom2);
2551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   at = mkPCast32x8(mce, at);
2552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return at;
2553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
2556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* binary64Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* at;
2559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   at = mkUifUV256(mce, vatom1, vatom2);
2560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   at = mkPCast64x4(mce, at);
2561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return at;
2562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- V128-bit versions --- */
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatom1, vatom2);
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast8x16(mce, at);
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatom1, vatom2);
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast16x8(mce, at);
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatom1, vatom2);
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast32x4(mce, at);
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatom1, vatom2);
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast64x2(mce, at);
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- 64-bit versions --- */
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary8Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatom1, vatom2);
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast8x8(mce, at);
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary16Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatom1, vatom2);
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast16x4(mce, at);
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatom1, vatom2);
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast32x2(mce, at);
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary64Ix1 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatom1, vatom2);
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I64, at);
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- 32-bit versions --- */
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary8Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU32(mce, vatom1, vatom2);
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast8x4(mce, at);
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary16Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU32(mce, vatom1, vatom2);
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast16x2(mce, at);
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Generate shadow values from all kinds of IRExprs.    ---*/
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expr2vbits_Qop ( MCEnv* mce,
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IROp op,
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRAtom* atom1, IRAtom* atom2,
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRAtom* atom3, IRAtom* atom4 )
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom1 = expr2vbits( mce, atom1 );
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom2 = expr2vbits( mce, atom2 );
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom3 = expr2vbits( mce, atom3 );
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom4 = expr2vbits( mce, atom4 );
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom1));
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom2));
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom3));
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom4));
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom3));
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom4));
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom1,vatom1));
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom2,vatom2));
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom3,vatom3));
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom4,vatom4));
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MAddF64:
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MAddF64r32:
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MSubF64:
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MSubF64r32:
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x F64 x F64 x F64 -> F64 */
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy4(mce, Ity_I64, vatom1, vatom2, vatom3, vatom4);
2695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_MAddF32:
2697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_MSubF32:
2698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* I32(rm) x F32 x F32 x F32 -> F32 */
2699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy4(mce, Ity_I32, vatom1, vatom2, vatom3, vatom4);
2700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* V256-bit data-steering */
2702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_64x4toV256:
2703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return assignNew('V', mce, Ity_V256,
2704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          IRExpr_Qop(op, vatom1, vatom2, vatom3, vatom4));
2705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIROp(op);
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:expr2vbits_Qop");
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expr2vbits_Triop ( MCEnv* mce,
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IROp op,
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRAtom* atom1, IRAtom* atom2, IRAtom* atom3 )
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom1 = expr2vbits( mce, atom1 );
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom2 = expr2vbits( mce, atom2 );
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom3 = expr2vbits( mce, atom3 );
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom1));
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom2));
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom3));
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom3));
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom1,vatom1));
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom2,vatom2));
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom3,vatom3));
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
2732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_AddF128:
2733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_AddD128:
2734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_SubF128:
2735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SubD128:
2736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_MulF128:
2737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_MulD128:
2738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivF128:
2739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_DivD128:
2740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_QuantizeD128:
2741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* I32(rm) x F128/D128 x F128/D128 -> F128/D128 */
2742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy3(mce, Ity_I128, vatom1, vatom2, vatom3);
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AddF64:
2744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_AddD64:
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AddF64r32:
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SubF64:
2747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SubD64:
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SubF64r32:
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulF64:
2750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_MulD64:
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulF64r32:
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivF64:
2753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_DivD64:
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivF64r32:
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ScaleF64:
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Yl2xF64:
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Yl2xp1F64:
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AtanF64:
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PRemF64:
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PRem1F64:
2761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_QuantizeD64:
2762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* I32(rm) x F64/D64 x F64/D64 -> F64/D64 */
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy3(mce, Ity_I64, vatom1, vatom2, vatom3);
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PRemC3210F64:
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PRem1C3210F64:
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x F64 x F64 -> I32 */
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy3(mce, Ity_I32, vatom1, vatom2, vatom3);
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AddF32:
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SubF32:
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulF32:
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivF32:
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x F32 x F32 -> I32 */
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy3(mce, Ity_I32, vatom1, vatom2, vatom3);
2774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SignificanceRoundD64:
2775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* IRRoundingMode(I32) x I8 x D64 -> D64 */
2776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkLazy3(mce, Ity_I64, vatom1, vatom2, vatom3);
2777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SignificanceRoundD128:
2778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* IRRoundingMode(I32) x I8 x D128 -> D128 */
2779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkLazy3(mce, Ity_I128, vatom1, vatom2, vatom3);
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ExtractV128:
2781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom3, NULL);
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, triop(op, vatom1, vatom2, atom3));
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Extract64:
2784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom3, NULL);
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, triop(op, vatom1, vatom2, atom3));
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetElem8x8:
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetElem16x4:
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetElem32x2:
2789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, triop(op, vatom1, atom2, vatom3));
2791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* BCDIops */
2792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_BCDAdd:
2793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_BCDSub:
2794436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         complainIfUndefined(mce, atom3, NULL);
2795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return assignNew('V', mce, Ity_V128, triop(op, vatom1, vatom2, atom3));
2796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2797436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Vector FP with rounding mode as the first arg */
2798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Add64Fx2:
2799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Sub64Fx2:
2800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Mul64Fx2:
2801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Div64Fx2:
2802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return binary64Fx2_w_rm(mce, vatom1, vatom2, vatom3);
2803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Add32Fx4:
2805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Sub32Fx4:
2806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Mul32Fx4:
2807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Div32Fx4:
2808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        return binary32Fx4_w_rm(mce, vatom1, vatom2, vatom3);
2809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Add64Fx4:
2811436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Sub64Fx4:
2812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Mul64Fx4:
2813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Div64Fx4:
2814436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return binary64Fx4_w_rm(mce, vatom1, vatom2, vatom3);
2815436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Add32Fx8:
2817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Sub32Fx8:
2818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Mul32Fx8:
2819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Div32Fx8:
2820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return binary32Fx8_w_rm(mce, vatom1, vatom2, vatom3);
2821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIROp(op);
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:expr2vbits_Triop");
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expr2vbits_Binop ( MCEnv* mce,
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IROp op,
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRAtom* atom1, IRAtom* atom2 )
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  and_or_ty;
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*uifu)    (MCEnv*, IRAtom*, IRAtom*);
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*difd)    (MCEnv*, IRAtom*, IRAtom*);
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom1 = expr2vbits( mce, atom1 );
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom2 = expr2vbits( mce, atom2 );
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom1));
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom2));
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom1,vatom1));
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom2,vatom2));
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32-bit SIMD */
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x2:
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HAdd16Ux2:
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HAdd16Sx2:
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x2:
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HSub16Ux2:
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HSub16Sx2:
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx2:
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx2:
2860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_QSub16Ux2:
2861436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QAdd16Ux2:
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary16Ix2(mce, vatom1, vatom2);
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x4:
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HAdd8Ux4:
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HAdd8Sx4:
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x4:
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HSub8Ux4:
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HSub8Sx4:
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux4:
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux4:
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx4:
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx4:
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary8Ix4(mce, vatom1, vatom2);
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64-bit SIMD */
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN8x8:
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x4:
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x2:
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN8x8:
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x4:
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x2:
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x4:
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x2:
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN8x8:
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Same scheme as with all other shifts. */
2888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2));
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx4:
2892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx8:
2893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux8:
2894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorNarrowBin64(mce, op, vatom1, vatom2);
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Ux8:
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Sx8:
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Ux8:
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Sx8:
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Ux8:
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx8:
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux8:
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x8:
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Sx8:
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Ux8:
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x8:
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx8:
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux8:
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal8x8:
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl8x8:
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x8:
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul8x8:
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PolynomialMul8x8:
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary8Ix8(mce, vatom1, vatom2);
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Sx4:
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Ux4:
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Sx4:
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Ux4:
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Ux4:
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Ux4:
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx4:
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x4:
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul16x4:
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Sx4:
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Ux4:
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Sx4:
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Ux4:
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16x4:
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx4:
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Ux4:
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal16x4:
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl16x4:
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x4:
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulHi16Sx4:
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QRDMulHi16Sx4:
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary16Ix4(mce, vatom1, vatom2);
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32x2:
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32x2:
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Sx2:
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Ux2:
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Sx2:
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Ux2:
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Sx2:
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Ux2:
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32x2:
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32x2:
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Ux2:
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Sx2:
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Ux2:
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Sx2:
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal32x2:
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl32x2:
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulHi32Sx2:
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QRDMulHi32Sx2:
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32Ix2(mce, vatom1, vatom2);
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub64Ux1:
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub64Sx1:
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd64Ux1:
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd64Sx1:
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal64x1:
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl64x1:
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal64x1:
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary64Ix1(mce, vatom1, vatom2);
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN8Sx8:
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN8x8:
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN8x8:
2971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x8(mce, vatom1);
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN16Sx4:
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN16x4:
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN16x4:
2977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x4(mce, vatom1);
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN32Sx2:
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN32x2:
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN32x2:
2983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce, vatom1);
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN64Sx1:
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN64x1:
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN64x1:
2989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce, vatom1);
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax32Sx2:
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax32Ux2:
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin32Sx2:
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin32Ux2:
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax32Fx2:
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin32Fx2:
2998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return assignNew('V', mce, Ity_I64,
2999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_PwMax32Ux2,
3000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkPCast32x2(mce, vatom1),
3001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkPCast32x2(mce, vatom2)));
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax16Sx4:
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax16Ux4:
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin16Sx4:
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin16Ux4:
3007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return assignNew('V', mce, Ity_I64,
3008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_PwMax16Ux4,
3009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkPCast16x4(mce, vatom1),
3010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkPCast16x4(mce, vatom2)));
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax8Sx8:
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax8Ux8:
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin8Sx8:
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin8Ux8:
3016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return assignNew('V', mce, Ity_I64,
3017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_PwMax8Ux8,
3018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkPCast8x8(mce, vatom1),
3019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkPCast8x8(mce, vatom2)));
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd32x2:
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd32Fx2:
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce,
3024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assignNew('V', mce, Ity_I64,
3025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         binop(Iop_PwAdd32x2,
3026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkPCast32x2(mce, vatom1),
3027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               mkPCast32x2(mce, vatom2))));
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd16x4:
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x4(mce,
3031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assignNew('V', mce, Ity_I64,
3032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         binop(op, mkPCast16x4(mce, vatom1),
3033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   mkPCast16x4(mce, vatom2))));
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd8x8:
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x8(mce,
3037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               assignNew('V', mce, Ity_I64,
3038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         binop(op, mkPCast8x8(mce, vatom1),
3039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                   mkPCast8x8(mce, vatom2))));
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl8x8:
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr8x8:
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar8x8:
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal8x8:
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(mce,
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2)),
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast8x8(mce,vatom2)
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl16x4:
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr16x4:
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar16x4:
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal16x4:
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(mce,
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2)),
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast16x4(mce,vatom2)
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl32x2:
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr32x2:
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar32x2:
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal32x2:
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(mce,
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2)),
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast32x2(mce,vatom2)
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64-bit data-steering */
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO32x2:
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO16x4:
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO8x8:
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI32x2:
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI16x4:
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI8x8:
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes8x8:
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes8x8:
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes16x4:
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes16x4:
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes8x8:
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes8x8:
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes16x4:
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes16x4:
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(op, vatom1, vatom2));
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem8x8:
3086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I8, binop(op, vatom1, atom2));
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem16x4:
3089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, binop(op, vatom1, atom2));
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem32x2:
3092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, binop(op, vatom1, atom2));
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Perm8x8: rearrange values in left arg using steering values
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        from right arg.  So rearrange the vbits in the same way but
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pessimise wrt steering values. */
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Perm8x8:
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2)),
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast8x8(mce, vatom2)
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V128-bit SIMD */
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN8x16:
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x8:
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x4:
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN64x2:
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN8x16:
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x8:
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x4:
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN64x2:
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN8x16:
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x8:
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x4:
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN64x2:
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Same scheme as with all other shifts.  Note: 22 Oct 05:
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            this is wrong now, scalar shifts are done properly lazily.
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Vector shifts should be fixed too. */
3122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2));
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V x V shifts/rotates are done using the standard lazy scheme. */
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl8x16:
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr8x16:
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar8x16:
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal8x16:
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol8x16:
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce,
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast8x16(mce,vatom2)
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl16x8:
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr16x8:
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar16x8:
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal16x8:
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol16x8:
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce,
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast16x8(mce,vatom2)
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl32x4:
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr32x4:
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar32x4:
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal32x4:
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol32x4:
3151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Rol64x2:
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce,
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast32x4(mce,vatom2)
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl64x2:
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr64x2:
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar64x2:
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal64x2:
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce,
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast64x2(mce,vatom2)
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32ToFixed32Ux4_RZ:
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32ToFixed32Sx4_RZ:
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Fixed32UToF32x4_RN:
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Fixed32SToF32x4_RN:
3170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce, vatom1);
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32ToFixed32Ux2_RZ:
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32ToFixed32Sx2_RZ:
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Fixed32UToF32x2_RN:
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Fixed32SToF32x2_RN:
3177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce, vatom1);
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux16:
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx16:
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x16:
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Ux16:
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Sx16:
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Ux16:
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Sx16:
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Sx16:
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Ux16:
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x16:
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Ux16:
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Sx16:
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux16:
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx16:
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal8x16:
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl8x16:
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x16:
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul8x16:
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PolynomialMul8x16:
3199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_PolynomialMulAdd8x16:
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary8Ix16(mce, vatom1, vatom2);
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Ux8:
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx8:
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x8:
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul16x8:
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Sx8:
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Ux8:
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Sx8:
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Ux8:
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Sx8:
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Ux8:
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Sx8:
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Ux8:
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16x8:
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Ux8:
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Sx8:
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Ux8:
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx8:
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal16x8:
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl16x8:
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x8:
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulHi16Sx8:
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QRDMulHi16Sx8:
3224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_PolynomialMulAdd16x8:
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary16Ix8(mce, vatom1, vatom2);
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32x4:
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Sx4:
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Ux4:
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32x4:
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Sx4:
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Ux4:
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Sx4:
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Ux4:
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal32x4:
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl32x4:
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg32Ux4:
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg32Sx4:
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32x4:
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Ux4:
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Sx4:
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Ux4:
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Sx4:
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32x4:
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulHi32Sx4:
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QRDMulHi32Sx4:
3247436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_PolynomialMulAdd32x4:
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32Ix4(mce, vatom1, vatom2);
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64x2:
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64x2:
3252436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Max64Sx2:
3253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Max64Ux2:
3254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Min64Sx2:
3255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Min64Ux2:
3256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpEQ64x2:
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT64Sx2:
3258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpGT64Ux2:
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal64x2:
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl64x2:
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd64Ux2:
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd64Sx2:
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub64Ux2:
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub64Sx2:
3265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_PolynomialMulAdd64x2:
3266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CipherV128:
3267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CipherLV128:
3268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_NCipherV128:
3269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_NCipherLV128:
3270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        return binary64Ix2(mce, vatom1, vatom2);
3271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QNarrowBin64Sto32Sx4:
3273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QNarrowBin64Uto32Ux4:
3274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8:
3275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Uto16Ux8:
3276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Ux8:
3277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16:
3278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Uto8Ux16:
3279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux16:
3280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorNarrowBinV128(mce, op, vatom1, vatom2);
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min64Fx2:
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max64Fx2:
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64Fx2:
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64Fx2:
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64Fx2:
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN64Fx2:
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary64Fx2(mce, vatom1, vatom2);
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64F0x2:
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul64F0x2:
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min64F0x2:
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max64F0x2:
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div64F0x2:
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64F0x2:
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64F0x2:
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64F0x2:
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN64F0x2:
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64F0x2:
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary64F0x2(mce, vatom1, vatom2);
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Fx4:
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Fx4:
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32Fx4:
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32Fx4:
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32Fx4:
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN32Fx4:
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Fx4:
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGE32Fx4:
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recps32Fx4:
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rsqrts32Fx4:
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32Fx4(mce, vatom1, vatom2);
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32Fx2:
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32Fx2:
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Fx2:
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Fx2:
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32Fx2:
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Fx2:
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGE32Fx2:
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32Fx2:
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recps32Fx2:
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rsqrts32Fx2:
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32Fx2(mce, vatom1, vatom2);
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32F0x4:
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32F0x4:
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32F0x4:
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32F0x4:
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div32F0x4:
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32F0x4:
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32F0x4:
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32F0x4:
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN32F0x4:
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32F0x4:
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32F0x4(mce, vatom1, vatom2);
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN8Sx16:
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN8x16:
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN8x16:
3341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x16(mce, vatom1);
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN16Sx8:
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN16x8:
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN16x8:
3347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x8(mce, vatom1);
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN32Sx4:
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN32x4:
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN32x4:
3353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce, vatom1);
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN64Sx2:
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN64x2:
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN64x2:
3359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce, vatom1);
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull32Sx2:
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull32Ux2:
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulLong32Sx2:
3365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorWidenI64(mce, Iop_Widen32Sto64x2,
3366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    mkUifU64(mce, vatom1, vatom2));
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull16Sx4:
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull16Ux4:
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulLong16Sx4:
3371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorWidenI64(mce, Iop_Widen16Sto32x4,
3372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    mkUifU64(mce, vatom1, vatom2));
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull8Sx8:
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull8Ux8:
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PolynomialMull8x8:
3377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorWidenI64(mce, Iop_Widen8Sto16x8,
3378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    mkUifU64(mce, vatom1, vatom2));
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd32x4:
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce,
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, binop(op, mkPCast32x4(mce, vatom1),
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast32x4(mce, vatom2))));
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd16x8:
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x8(mce,
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, binop(op, mkPCast16x8(mce, vatom1),
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast16x8(mce, vatom2))));
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd8x16:
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x16(mce,
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, binop(op, mkPCast8x16(mce, vatom1),
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast8x16(mce, vatom2))));
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V128-bit data-steering */
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetV128lo32:
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetV128lo64:
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLtoV128:
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO64x2:
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO32x4:
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO16x8:
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO8x16:
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI64x2:
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI32x4:
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI16x8:
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI8x16:
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes8x16:
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes16x8:
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes32x4:
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes8x16:
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes16x8:
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes32x4:
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes8x16:
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes16x8:
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes32x4:
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes8x16:
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes16x8:
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes32x4:
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, binop(op, vatom1, vatom2));
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem8x16:
3422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I8, binop(op, vatom1, atom2));
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem16x8:
3425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, binop(op, vatom1, atom2));
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem32x4:
3428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, binop(op, vatom1, atom2));
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem64x2:
3431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2));
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Perm8x16: rearrange values in left arg using steering values
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        from right arg.  So rearrange the vbits in the same way but
3436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        pessimise wrt steering values.  Perm32x4 ditto. */
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Perm8x16:
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast8x16(mce, vatom2)
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Perm32x4:
3444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkUifUV128(
3445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mce,
3446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
3447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkPCast32x4(mce, vatom2)
3448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                );
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* These two take the lower half of each 16-bit lane, sign/zero
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        extend it to 32, and multiply together, producing a 32x4
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        result (and implicitly ignoring half the operand bits).  So
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        treat it as a bunch of independent 16x8 operations, but then
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        do 32-bit shifts left-right to copy the lower half results
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (which are all 0s or all 1s due to PCasting in binary16Ix8)
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        into the upper half of each result lane. */
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven16Ux8:
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven16Sx8: {
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* at;
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = binary16Ix8(mce,vatom1,vatom2);
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = assignNew('V', mce, Ity_V128, binop(Iop_ShlN32x4, at, mkU8(16)));
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = assignNew('V', mce, Ity_V128, binop(Iop_SarN32x4, at, mkU8(16)));
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 return at;
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Same deal as Iop_MullEven16{S,U}x8 */
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven8Ux16:
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven8Sx16: {
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* at;
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = binary8Ix16(mce,vatom1,vatom2);
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = assignNew('V', mce, Ity_V128, binop(Iop_ShlN16x8, at, mkU8(8)));
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = assignNew('V', mce, Ity_V128, binop(Iop_SarN16x8, at, mkU8(8)));
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 return at;
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Same deal as Iop_MullEven16{S,U}x8 */
3477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_MullEven32Ux4:
3478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_MullEven32Sx4: {
3479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRAtom* at;
3480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         at = binary32Ix4(mce,vatom1,vatom2);
3481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         at = assignNew('V', mce, Ity_V128, binop(Iop_ShlN64x2, at, mkU8(32)));
3482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         at = assignNew('V', mce, Ity_V128, binop(Iop_SarN64x2, at, mkU8(32)));
3483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return at;
3484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3485436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* narrow 2xV128 into 1xV128, hi half from left arg, in a 2 x
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         32x4 -> 16x8 laneage, discarding the upper half of each lane.
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Simply apply same op to the V bits, since this really no more
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         than a data steering operation. */
3490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin32to16x8:
3491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin16to8x16:
3492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_NarrowBin64to32x4:
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128,
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(op, vatom1, vatom2));
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrV128:
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlV128:
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Same scheme as with all other shifts.  Note: 10 Nov 05:
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            this is wrong now, scalar shifts are done properly lazily.
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Vector shifts should be fixed too. */
3501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         complainIfUndefined(mce, atom2, NULL);
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2));
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* SHA Iops */
3505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_SHA256:
3506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_SHA512:
3507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         complainIfUndefined(mce, atom2, NULL);
3508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2));
3509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* I128-bit data-steering */
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLto128:
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I128, binop(op, vatom1, vatom2));
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* V256-bit SIMD */
3515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Max64Fx4:
3517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Min64Fx4:
3518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return binary64Fx4(mce, vatom1, vatom2);
3519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Max32Fx8:
3521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Min32Fx8:
3522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return binary32Fx8(mce, vatom1, vatom2);
3523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* V256-bit data-steering */
3525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_V128HLtoV256:
3526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return assignNew('V', mce, Ity_V256, binop(op, vatom1, vatom2));
3527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Scalar floating point */
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F32toI64S:
3531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F32toI64U:
3532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* I32(rm) x F32 -> I64 */
3533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64StoF32:
3536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* I32(rm) x I64 -> F32 */
3537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toInt:
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF32:
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toI64S:
3542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F64toI64U:
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I64StoF64:
3544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64UtoF64:
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SinF64:
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CosF64:
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_TanF64:
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_2xm1F64:
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SqrtF64:
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x I64/F64 -> I64/F64 */
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlD64:
3554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrD64:
3555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_RoundD64toInt:
3556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* I32(rm) x D64 -> D64 */
3557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlD128:
3560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrD128:
3561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_RoundD128toInt:
3562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* I32(rm) x D128 -> D128 */
3563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkLazy2(mce, Ity_I128, vatom1, vatom2);
3564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D64toI64S:
3566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D64toI64U:
3567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_I64StoD64:
3568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I64UtoD64:
3569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* I32(rm) x I64/D64 -> D64/I64 */
3570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F32toD32:
3573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F64toD32:
3574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F128toD32:
3575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D32toF32:
3576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D64toF32:
3577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D128toF32:
3578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* I32(rm) x F32/F64/F128/D32/D64/D128 -> D32/F32 */
3579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F32toD64:
3582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F64toD64:
3583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F128toD64:
3584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D32toF64:
3585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D64toF64:
3586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D128toF64:
3587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* I32(rm) x F32/F64/F128/D32/D64/D128 -> D64/F64 */
3588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F32toD128:
3591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F64toD128:
3592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F128toD128:
3593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D32toF128:
3594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D64toF128:
3595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D128toF128:
3596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* I32(rm) x F32/F64/F128/D32/D64/D128 -> D128/F128 */
3597436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return mkLazy2(mce, Ity_I128, vatom1, vatom2);
3598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32toInt:
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SqrtF32:
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x I32/F32 -> I32/F32 */
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_SqrtF128:
3605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* I32(rm) x F128 -> F128 */
3606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I128, vatom1, vatom2);
3607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I32StoF32:
3609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I32UtoF32:
3610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F32toI32S:
3611436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F32toI32U:
3612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* First arg is I32 (rounding mode), second is F32/I32 (data). */
3613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128toI32S: /* IRRoundingMode(I32) x F128 -> signed I32  */
3616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F128toI32U: /* IRRoundingMode(I32) x F128 -> unsigned I32  */
3617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128toF32:  /* IRRoundingMode(I32) x F128 -> F32         */
3618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D128toI32S: /* IRRoundingMode(I32) x D128 -> signed I32  */
3619436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D128toI32U: /* IRRoundingMode(I32) x D128 -> unsigned I32  */
3620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128toI64S: /* IRRoundingMode(I32) x F128 -> signed I64  */
3623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_F128toI64U: /* IRRoundingMode(I32) x F128 -> unsigned I64  */
3624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128toF64:  /* IRRoundingMode(I32) x F128 -> F64         */
3625436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D128toD64:  /* IRRoundingMode(I64) x D128 -> D64 */
3626436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D128toI64S: /* IRRoundingMode(I64) x D128 -> signed I64  */
3627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D128toI64U: /* IRRoundingMode(I32) x D128 -> unsigned I64  */
3628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F64HLtoF128:
3631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D64HLtoD128:
3632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return assignNew('V', mce, Ity_I128,
3633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_64HLto128, vatom1, vatom2));
3634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toI32U:
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toI32S:
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toF32:
3638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64UtoF32:
3639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D64toI32U:
3640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_D64toI32S:
3641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* First arg is I32 (rounding mode), second is F64/D64 (data). */
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D64toD32:
3645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* First arg is I32 (rounding mode), second is D64 (data). */
3646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toI16S:
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* First arg is I32 (rounding mode), second is F64 (data). */
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I16, vatom1, vatom2);
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_InsertExpD64:
3653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /*  I64 x I64 -> D64 */
3654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_InsertExpD128:
3657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /*  I64 x I128 -> D128 */
3658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkLazy2(mce, Ity_I128, vatom1, vatom2);
3659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpF32:
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpF64:
3662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpF128:
3663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpD64:
3664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpD128:
3665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpExpD64:
3666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpExpD128:
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* non-FP after here */
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivModU64to32:
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivModS64to32:
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivModU128to64:
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivModS128to64:
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I128, vatom1, vatom2);
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_8HLto16:
3680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return assignNew('V', mce, Ity_I16, binop(op, vatom1, vatom2));
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16HLto32:
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, binop(op, vatom1, vatom2));
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32HLto64:
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(op, vatom1, vatom2));
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivModS64to64:
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS64:
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU64: {
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vLo64 = mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vHi64 = mkPCastTo(mce, Ity_I64, vLo64);
3691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return assignNew('V', mce, Ity_I128,
3692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_64HLto128, vHi64, vLo64));
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS32:
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU32: {
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
3699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return assignNew('V', mce, Ity_I64,
3700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_32HLto64, vHi32, vLo32));
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS16:
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU16: {
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
3707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return assignNew('V', mce, Ity_I32,
3708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          binop(Iop_16HLto32, vHi16, vLo16));
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS8:
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU8: {
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sad8Ux4: /* maybe we could do better?  ftm, do mkLazy2. */
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivS32:
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivU32:
3721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivU32E:
3722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivS32E:
3723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_QAdd32S: /* could probably do better */
3724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_QSub32S: /* could probably do better */
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivS64:
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivU64:
3729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivS64E:
3730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivU64E:
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32:
3734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (mce->bogusLiterals || mce->useLLVMworkarounds)
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveAddSub(mce,True,Ity_I32,
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   vatom1,vatom2, atom1,atom2);
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_AddSub32;
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32:
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveAddSub(mce,False,Ity_I32,
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   vatom1,vatom2, atom1,atom2);
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_AddSub32;
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cheap_AddSub32:
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32:
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpORD32S:
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpORD32U:
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpORD64S:
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpORD64U:
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return doCmpORD(mce, op, vatom1,vatom2, atom1,atom2);
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64:
3757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (mce->bogusLiterals || mce->useLLVMworkarounds)
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveAddSub(mce,True,Ity_I64,
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   vatom1,vatom2, atom1,atom2);
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_AddSub64;
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64:
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveAddSub(mce,False,Ity_I64,
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   vatom1,vatom2, atom1,atom2);
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_AddSub64;
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cheap_AddSub64:
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul64:
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul16:
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16:
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16:
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Mul8:
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8:
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8:
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64:
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNE64:
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            goto expensive_cmp64;
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_cmp64;
3789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      expensive_cmp64:
3791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ExpCmpNE64:
3792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return expensiveCmpEQorNE(mce,Ity_I64, vatom1,vatom2, atom1,atom2 );
3793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cheap_cmp64:
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64S: case Iop_CmpLE64U:
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64U: case Iop_CmpLT64S:
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I1, mkUifU64(mce, vatom1,vatom2));
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32:
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNE32:
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            goto expensive_cmp32;
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_cmp32;
3805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      expensive_cmp32:
3807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ExpCmpNE32:
3808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
3809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cheap_cmp32:
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32S: case Iop_CmpLE32U:
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32U: case Iop_CmpLT32S:
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16: case Iop_CmpNE16:
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ExpCmpNE16:
3819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return expensiveCmpEQorNE(mce,Ity_I16, vatom1,vatom2, atom1,atom2 );
3820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8: case Iop_CmpNE8:
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CasCmpEQ8:  case Iop_CasCmpNE8:
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CasCmpEQ16: case Iop_CasCmpNE16:
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CasCmpEQ32: case Iop_CasCmpNE32:
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CasCmpEQ64: case Iop_CasCmpNE64:
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Just say these all produce a defined result, regardless
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            of their arguments.  See COMMENT_ON_CasCmpEQ in this file. */
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I1, definedOfType(Ity_I1));
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return scalarShift( mce, Ity_I64, op, vatom1,vatom2, atom1,atom2 );
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return scalarShift( mce, Ity_I32, op, vatom1,vatom2, atom1,atom2 );
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return scalarShift( mce, Ity_I16, op, vatom1,vatom2, atom1,atom2 );
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Shl8: case Iop_Shr8: case Iop_Sar8:
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return scalarShift( mce, Ity_I8, op, vatom1,vatom2, atom1,atom2 );
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_AndV256:
3845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         uifu = mkUifUV256; difd = mkDifDV256;
3846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         and_or_ty = Ity_V256; improve = mkImproveANDV256; goto do_And_Or;
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AndV128:
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifUV128; difd = mkDifDV128;
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And64:
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU64; difd = mkDifD64;
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And32:
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU32; difd = mkDifD32;
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And16:
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU16; difd = mkDifD16;
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And8:
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU8; difd = mkDifD8;
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_OrV256:
3864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         uifu = mkUifUV256; difd = mkDifDV256;
3865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         and_or_ty = Ity_V256; improve = mkImproveORV256; goto do_And_Or;
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_OrV128:
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifUV128; difd = mkDifDV128;
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or64:
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU64; difd = mkDifD64;
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or32:
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU32; difd = mkDifD32;
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or16:
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU16; difd = mkDifD16;
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or8:
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU8; difd = mkDifD8;
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_And_Or:
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assignNew(
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            'V', mce,
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            and_or_ty,
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            difd(mce, uifu(mce, vatom1, vatom2),
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      difd(mce, improve(mce, atom1, vatom1),
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                improve(mce, atom2, vatom2) ) ) );
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor8:
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU8(mce, vatom1, vatom2);
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor16:
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU16(mce, vatom1, vatom2);
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor32:
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU32(mce, vatom1, vatom2);
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor64:
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(mce, vatom1, vatom2);
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_XorV128:
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce, vatom1, vatom2);
3901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_XorV256:
3902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkUifUV256(mce, vatom1, vatom2);
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3904436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* V256-bit SIMD */
3905436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3906436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ShrN16x16:
3907436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ShrN32x8:
3908436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ShrN64x4:
3909436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_SarN16x16:
3910436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_SarN32x8:
3911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ShlN16x16:
3912436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ShlN32x8:
3913436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ShlN64x4:
3914436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Same scheme as with all other shifts.  Note: 22 Oct 05:
3915436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            this is wrong now, scalar shifts are done properly lazily.
3916436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Vector shifts should be fixed too. */
3917436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         complainIfUndefined(mce, atom2, NULL);
3918436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return assignNew('V', mce, Ity_V256, binop(op, vatom1, atom2));
3919436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QSub8Ux32:
3921436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QSub8Sx32:
3922436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Sub8x32:
3923436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Min8Ux32:
3924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Min8Sx32:
3925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Max8Ux32:
3926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Max8Sx32:
3927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpGT8Sx32:
3928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpEQ8x32:
3929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Avg8Ux32:
3930436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QAdd8Ux32:
3931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QAdd8Sx32:
3932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Add8x32:
3933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return binary8Ix32(mce, vatom1, vatom2);
3934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3935436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QSub16Ux16:
3936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QSub16Sx16:
3937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Sub16x16:
3938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Mul16x16:
3939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_MulHi16Sx16:
3940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_MulHi16Ux16:
3941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Min16Sx16:
3942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Min16Ux16:
3943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Max16Sx16:
3944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Max16Ux16:
3945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpGT16Sx16:
3946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpEQ16x16:
3947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Avg16Ux16:
3948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QAdd16Ux16:
3949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_QAdd16Sx16:
3950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Add16x16:
3951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return binary16Ix16(mce, vatom1, vatom2);
3952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3953436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Sub32x8:
3954436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpGT32Sx8:
3955436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpEQ32x8:
3956436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Add32x8:
3957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Max32Ux8:
3958436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Max32Sx8:
3959436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Min32Ux8:
3960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Min32Sx8:
3961436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Mul32x8:
3962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return binary32Ix8(mce, vatom1, vatom2);
3963436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Sub64x4:
3965436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Add64x4:
3966436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpEQ64x4:
3967436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpGT64Sx4:
3968436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return binary64Ix4(mce, vatom1, vatom2);
3969436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3970436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     /* Perm32x8: rearrange values in left arg using steering values
3971436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        from right arg.  So rearrange the vbits in the same way but
3972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        pessimise wrt steering values. */
3973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Perm32x8:
3974436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return mkUifUV256(
3975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   mce,
3976436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   assignNew('V', mce, Ity_V256, binop(op, vatom1, atom2)),
3977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   mkPCast32x8(mce, vatom2)
3978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                );
3979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIROp(op);
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:expr2vbits_Binop");
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* For the widening operations {8,16,32}{U,S}to{16,32,64}, the
3991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      selection of shadow operation implicitly duplicates the logic in
3992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      do_shadow_LoadG and should be kept in sync (in the very unlikely
3993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      event that the interpretation of such widening ops changes in
3994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      future).  See comment in do_shadow_LoadG. */
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom = expr2vbits( mce, atom );
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom));
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt64Fx2:
40002ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      case Iop_Abs64Fx2:
40012ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      case Iop_Neg64Fx2:
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary64Fx2(mce, vatom);
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt64F0x2:
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary64F0x2(mce, vatom);
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Sqrt32Fx8:
4008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_RSqrt32Fx8:
4009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Recip32Fx8:
4010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return unary32Fx8(mce, vatom);
4011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Sqrt64Fx4:
4013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return unary64Fx4(mce, vatom);
4014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt32Fx4:
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt32Fx4:
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32Fx4:
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32UtoFx4:
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32StoFx4:
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QFtoI32Ux4_RZ:
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QFtoI32Sx4_RZ:
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32x4_RM:
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32x4_RP:
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32x4_RN:
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32x4_RZ:
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32x4:
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs32Fx4:
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Neg32Fx4:
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rsqrte32Fx4:
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary32Fx4(mce, vatom);
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32UtoFx2:
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32StoFx2:
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32Fx2:
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32x2:
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs32Fx2:
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Neg32Fx2:
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rsqrte32Fx2:
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary32Fx2(mce, vatom);
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt32F0x4:
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt32F0x4:
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32F0x4:
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary32F0x4(mce, vatom);
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32UtoV128:
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64UtoV128:
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup8x16:
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup16x8:
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup32x4:
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse16_8x16:
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse32_8x16:
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse32_16x8:
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_8x16:
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_16x8:
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_32x4:
4057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_V256toV128_1: case Iop_V256toV128_0:
40582ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      case Iop_ZeroHI64ofV128:
40592ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      case Iop_ZeroHI96ofV128:
40602ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      case Iop_ZeroHI112ofV128:
40612ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov      case Iop_ZeroHI120ofV128:
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, unop(op, vatom));
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128HItoF64:  /* F128 -> high half of F128 */
4065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D128HItoD64:  /* D128 -> high half of D128 */
4066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return assignNew('V', mce, Ity_I64, unop(Iop_128HIto64, vatom));
4067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128LOtoF64:  /* F128 -> low  half of F128 */
4068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D128LOtoD64:  /* D128 -> low  half of D128 */
4069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return assignNew('V', mce, Ity_I64, unop(Iop_128to64, vatom));
4070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
4071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NegF128:
4072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_AbsF128:
4073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkPCastTo(mce, Ity_I128, vatom);
4074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
4075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I32StoF128: /* signed I32 -> F128 */
4076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64StoF128: /* signed I64 -> F128 */
4077436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I32UtoF128: /* unsigned I32 -> F128 */
4078436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I64UtoF128: /* unsigned I64 -> F128 */
4079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F32toF128:  /* F32 -> F128 */
4080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F64toF128:  /* F64 -> F128 */
4081436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I32StoD128: /* signed I64 -> D128 */
4082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_I64StoD128: /* signed I64 -> D128 */
4083436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I32UtoD128: /* unsigned I32 -> D128 */
4084436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I64UtoD128: /* unsigned I64 -> D128 */
4085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkPCastTo(mce, Ity_I128, vatom);
4086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32toF64:
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32StoF64:
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32UtoF64:
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NegF64:
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AbsF64:
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Est5FRSqrt:
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF64_NEAREST:
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF64_NegINF:
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF64_PosINF:
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF64_ZERO:
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz64:
4098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D32toD64:
4099436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I32StoD64:
4100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I32UtoD64:
4101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ExtractExpD64:    /* D64  -> I64 */
4102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ExtractExpD128:   /* D128 -> I64 */
4103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ExtractSigD64:    /* D64  -> I64 */
4104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ExtractSigD128:   /* D128 -> I64 */
4105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_DPBtoBCD:
4106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_BCDtoDPB:
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I64, vatom);
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D64toD128:
4110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mkPCastTo(mce, Ity_I128, vatom);
4111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz32:
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_TruncF64asF32:
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NegF32:
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AbsF32:
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I32, vatom);
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Ctz32:
4119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Ctz64:
4120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return expensiveCountTrailingZeroes(mce, op, atom, vatom);
4121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Uto64:
4123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_1Sto64:
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto64:
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto64:
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Uto64:
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Sto64:
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Sto64:
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Uto64:
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to64:
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128HIto64:
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_128HIto64:
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_128to64:
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup8x8:
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup16x4:
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup32x2:
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse16_8x8:
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse32_8x8:
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse32_16x4:
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_8x8:
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_16x4:
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_32x2:
4143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_V256to64_0: case Iop_V256to64_1:
4144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_V256to64_2: case Iop_V256to64_3:
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, unop(op, vatom));
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to32:
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HIto32:
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Uto32:
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto32:
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto32:
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Uto32:
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Sto32:
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto32:
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to32:
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, unop(op, vatom));
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto16:
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto16:
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to16:
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32HIto16:
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to16:
4163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_GetMSBs8x16:
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, unop(op, vatom));
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Uto8:
4167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_1Sto8:
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16to8:
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16HIto8:
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to8:
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to8:
4172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_GetMSBs8x8:
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I8, unop(op, vatom));
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to1:
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I1, unop(Iop_32to1, vatom));
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to1:
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I1, unop(Iop_64to1, vatom));
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF64asI64:
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpI64asF64:
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpI32asF32:
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF32asI32:
4185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ReinterpI64asD64:
4186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ReinterpD64asI64:
4187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_NotV256:
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NotV128:
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not64:
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not32:
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not16:
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not8:
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not1:
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return vatom;
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ8x8:
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cnt8x8:
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz8Sx8:
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls8Sx8:
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs8x8:
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x8(mce, vatom);
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ8x16:
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cnt8x16:
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz8Sx16:
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls8Sx16:
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs8x16:
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x16(mce, vatom);
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ16x4:
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz16Sx4:
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls16Sx4:
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs16x4:
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x4(mce, vatom);
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ16x8:
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz16Sx8:
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls16Sx8:
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs16x8:
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x8(mce, vatom);
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ32x2:
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz32Sx2:
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls32Sx2:
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_FtoI32Ux2_RZ:
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_FtoI32Sx2_RZ:
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs32x2:
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce, vatom);
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ32x4:
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz32Sx4:
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls32Sx4:
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_FtoI32Ux4_RZ:
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_FtoI32Sx4_RZ:
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs32x4:
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce, vatom);
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CmpwNEZ32:
4239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return mkPCastTo(mce, Ity_I32, vatom);
4240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpwNEZ64:
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I64, vatom);
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ64x2:
4245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_CipherSV128:
4246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_Clz64x2:
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast64x2(mce, vatom);
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_PwBitMtxXpose64x2:
4250436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return assignNew('V', mce, Ity_V128, unop(op, vatom));
4251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn16to8x8:
4253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn32to16x4:
4254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn64to32x2:
4255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Sx8:
4256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Ux8:
4257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Uto8Ux8:
4258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Sx4:
4259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Ux4:
4260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Uto16Ux4:
4261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Sx2:
4262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Ux2:
4263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Uto32Ux2:
4264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorNarrowUnV128(mce, op, vatom);
4265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
4266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen8Sto16x8:
4267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen8Uto16x8:
4268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen16Sto32x4:
4269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen16Uto32x4:
4270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen32Sto64x2:
4271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen32Uto64x2:
4272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorWidenI64(mce, op, vatom);
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL32Ux2:
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL32Sx2:
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I64,
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_I64, unop(op, mkPCast32x2(mce, vatom))));
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL16Ux4:
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL16Sx4:
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce,
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_I64, unop(op, mkPCast16x4(mce, vatom))));
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL8Ux8:
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL8Sx8:
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x4(mce,
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_I64, unop(op, mkPCast8x8(mce, vatom))));
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL32Ux4:
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL32Sx4:
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast64x2(mce,
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, unop(op, mkPCast32x4(mce, vatom))));
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL16Ux8:
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL16Sx8:
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce,
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, unop(op, mkPCast16x8(mce, vatom))));
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL8Ux16:
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL8Sx16:
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x8(mce,
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, unop(op, mkPCast8x16(mce, vatom))));
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4304051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov      // TODO: is this correct?
4305051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov      case Iop_AddLV8Ux16:
4306051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov      case Iop_AddLV8Sx16:
4307051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov         return assignNew('V', mce, Ity_V128, unop(op, mkPCast8x16(mce, vatom)));
4308051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov
4309051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov      case Iop_AddLV16Ux8:
4310051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov      case Iop_AddLV16Sx8:
4311051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov         return assignNew('V', mce, Ity_V128, unop(op, mkPCast16x8(mce, vatom)));
4312051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov
4313051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov      case Iop_AddLV32Ux4:
4314051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov      case Iop_AddLV32Sx4:
4315051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov         return assignNew('V', mce, Ity_V128, unop(op, mkPCast32x4(mce, vatom)));
4316051d3b5d6376aa10a65793c3c2267d6ab233b896Dmitriy Ivanov
4317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64UtoF32:
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIROp(op);
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:expr2vbits_Unop");
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Worker function -- do not call directly.  See comments on
4326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   expr2vbits_Load for the meaning of |guard|.
4327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Generates IR to (1) perform a definedness test of |addr|, (2)
4329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   perform a validity test of |addr|, and (3) return the Vbits for the
4330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   location indicated by |addr|.  All of this only happens when
4331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   |guard| is NULL or |guard| evaluates to True at run time.
4332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   If |guard| evaluates to False at run time, the returned value is
4334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   the IR-mandated 0x55..55 value, and no checks nor shadow loads are
4335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   performed.
4336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   The definedness of |guard| itself is not checked.  That is assumed
4338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   to have been done before this point, by the caller. */
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* expr2vbits_Load_WRK ( MCEnv* mce,
4341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              IREndness end, IRType ty,
4342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              IRAtom* addr, UInt bias, IRAtom* guard )
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,addr));
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(end == Iend_LE || end == Iend_BE);
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First, emit a definedness test for the address.  This also sets
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the address (shadow) to 'defined' following the test. */
4349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   complainIfUndefined( mce, addr, guard );
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now cook up a call to the relevant helper function, to read the
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      data V bits from shadow memory. */
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = shadowTypeV(ty);
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   void*        helper           = NULL;
4356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* hname            = NULL;
4357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Bool         ret_via_outparam = False;
4358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (end == Iend_LE) {
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
4361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_V256: helper = &MC_(helperc_LOADV256le);
4362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV256le)";
4363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        ret_via_outparam = True;
4364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_V128: helper = &MC_(helperc_LOADV128le);
4366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV128le)";
4367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        ret_via_outparam = True;
4368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I64:  helper = &MC_(helperc_LOADV64le);
4370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV64le)";
4371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I32:  helper = &MC_(helperc_LOADV32le);
4373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV32le)";
4374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I16:  helper = &MC_(helperc_LOADV16le);
4376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV16le)";
4377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I8:   helper = &MC_(helperc_LOADV8);
4379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV8)";
4380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         default:       ppIRType(ty);
4382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        VG_(tool_panic)("memcheck:expr2vbits_Load_WRK(LE)");
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
4386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_V256: helper = &MC_(helperc_LOADV256be);
4387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV256be)";
4388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        ret_via_outparam = True;
4389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_V128: helper = &MC_(helperc_LOADV128be);
4391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV128be)";
4392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        ret_via_outparam = True;
4393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I64:  helper = &MC_(helperc_LOADV64be);
4395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV64be)";
4396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I32:  helper = &MC_(helperc_LOADV32be);
4398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV32be)";
4399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4400436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I16:  helper = &MC_(helperc_LOADV16be);
4401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV16be)";
4402436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I8:   helper = &MC_(helperc_LOADV8);
4404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        hname = "MC_(helperc_LOADV8)";
4405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        break;
4406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         default:       ppIRType(ty);
4407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        VG_(tool_panic)("memcheck:expr2vbits_Load_WRK(BE)");
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(helper);
4412436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(hname);
4413436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Generate the actual address into addrAct. */
4415436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* addrAct;
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bias == 0) {
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addrAct = addr;
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp    mkAdd;
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom* eBias;
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType  tyAddr  = mce->hWordTy;
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mkAdd   = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eBias   = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addrAct = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBias) );
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We need to have a place to park the V bits we're just about to
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      read. */
4430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRTemp datavbits = newTemp(mce, ty, VSh);
4431436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4432436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Here's the call. */
4433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRDirty* di;
4434436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (ret_via_outparam) {
4435436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      di = unsafeIRDirty_1_N( datavbits,
4436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              2/*regparms*/,
4437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              hname, VG_(fnptr_to_fnentry)( helper ),
4438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              mkIRExprVec_2( IRExpr_VECRET(), addrAct ) );
4439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
4440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      di = unsafeIRDirty_1_N( datavbits,
4441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              1/*regparms*/,
4442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              hname, VG_(fnptr_to_fnentry)( helper ),
4443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              mkIRExprVec_1( addrAct ) );
4444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
4445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setHelperAnns( mce, di );
4447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (guard) {
4448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      di->guard = guard;
4449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Ideally the didn't-happen return value here would be all-ones
4450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         (all-undefined), so it'd be obvious if it got used
4451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         inadvertantly.  We can get by with the IR-mandated default
4452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         value (0b01 repeating, 0x55 etc) as that'll still look pretty
4453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         undefined if it ever leaks out. */
4454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'V', mce, IRStmt_Dirty(di) );
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkexpr(datavbits);
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Generate IR to do a shadow load.  The helper is expected to check
4462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   the validity of the address and return the V bits for that address.
4463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   This can optionally be controlled by a guard, which is assumed to
4464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   be True if NULL.  In the case where the guard is False at runtime,
4465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   the helper will return the didn't-do-the-call value of 0x55..55.
4466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Since that means "completely undefined result", the caller of
4467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   this function will need to fix up the result somehow in that
4468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case.
4469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Caller of this function is also expected to have checked the
4471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   definedness of |guard| before this point.
4472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* expr2vbits_Load ( MCEnv* mce,
4475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          IREndness end, IRType ty,
4476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          IRAtom* addr, UInt bias,
4477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          IRAtom* guard )
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(end == Iend_LE || end == Iend_BE);
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (shadowTypeV(ty)) {
4481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_I8:
4482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_I16:
4483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_I32:
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
4485436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_V128:
4486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_V256:
4487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return expr2vbits_Load_WRK(mce, end, ty, addr, bias, guard);
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("expr2vbits_Load");
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* The most general handler for guarded loads.  Assumes the
4495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   definedness of GUARD has already been checked by the caller.  A
4496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   GUARD of NULL is assumed to mean "always True".  Generates code to
4497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   check the definedness and validity of ADDR.
4498436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Generate IR to do a shadow load from ADDR and return the V bits.
4500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   The loaded type is TY.  The loaded data is then (shadow) widened by
4501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   using VWIDEN, which can be Iop_INVALID to denote a no-op.  If GUARD
4502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   evaluates to False at run time then the returned Vbits are simply
4503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VALT instead.  Note therefore that the argument type of VWIDEN must
4504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   be TY and the result type of VWIDEN must equal the type of VALT.
4505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
4506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
4507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* expr2vbits_Load_guarded_General ( MCEnv* mce,
4508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                          IREndness end, IRType ty,
4509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                          IRAtom* addr, UInt bias,
4510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                          IRAtom* guard,
4511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                          IROp vwiden, IRAtom* valt )
4512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
4513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Sanity check the conversion operation, and also set TYWIDE. */
4514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRType tyWide = Ity_INVALID;
4515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (vwiden) {
4516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_INVALID:
4517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tyWide = ty;
4518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
4519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_16Uto32: case Iop_16Sto32: case Iop_8Uto32: case Iop_8Sto32:
4520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tyWide = Ity_I32;
4521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
4522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
4523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(tool_panic)("memcheck:expr2vbits_Load_guarded_General");
4524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* If the guard evaluates to True, this will hold the loaded V bits
4527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      at TY.  If the guard evaluates to False, this will be all
4528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ones, meaning "all undefined", in which case we will have to
4529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      replace it using an ITE below. */
4530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* iftrue1
4531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = assignNew('V', mce, ty,
4532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  expr2vbits_Load(mce, end, ty, addr, bias, guard));
4533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Now (shadow-) widen the loaded V bits to the desired width.  In
4534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      the guard-is-False case, the allowable widening operators will
4535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      in the worst case (unsigned widening) at least leave the
4536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      pre-widened part as being marked all-undefined, and in the best
4537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case (signed widening) mark the whole widened result as
4538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      undefined.  Anyway, it doesn't matter really, since in this case
4539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      we will replace said value with the default value |valt| using an
4540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      ITE. */
4541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* iftrue2
4542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = vwiden == Iop_INVALID
4543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           ? iftrue1
4544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           : assignNew('V', mce, tyWide, unop(vwiden, iftrue1));
4545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* These are the V bits we will return if the load doesn't take
4546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      place. */
4547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* iffalse
4548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = valt;
4549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Prepare the cond for the ITE.  Convert a NULL cond into
4550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      something that iropt knows how to fold out later. */
4551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* cond
4552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = guard == NULL  ? mkU1(1)  : guard;
4553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* And assemble the final result. */
4554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return assignNew('V', mce, tyWide, IRExpr_ITE(cond, iftrue2, iffalse));
4555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
4556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
4558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* A simpler handler for guarded loads, in which there is no
4559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   conversion operation, and the default V bit return (when the guard
4560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   evaluates to False at runtime) is "all defined".  If there is no
4561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   guard expression or the guard is always TRUE this function behaves
4562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   like expr2vbits_Load.  It is assumed that definedness of GUARD has
4563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   already been checked at the call site. */
4564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
4565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* expr2vbits_Load_guarded_Simple ( MCEnv* mce,
4566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         IREndness end, IRType ty,
4567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         IRAtom* addr, UInt bias,
4568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         IRAtom *guard )
4569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
4570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return expr2vbits_Load_guarded_General(
4571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             mce, end, ty, addr, bias, guard, Iop_INVALID, definedOfType(ty)
4572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          );
4573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
4574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* expr2vbits_ITE ( MCEnv* mce,
4578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         IRAtom* cond, IRAtom* iftrue, IRAtom* iffalse )
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom *vbitsC, *vbits0, *vbits1;
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty;
4582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Given ITE(cond, iftrue,  iffalse),  generate
4583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ITE(cond, iftrue#, iffalse#) `UifU` PCast(cond#)
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      That is, steer the V bits like the originals, but trash the
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      result if the steering value is undefined.  This gives
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lazy propagation. */
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cond));
4588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(isOriginalAtom(mce, iftrue));
4589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(isOriginalAtom(mce, iffalse));
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vbitsC = expr2vbits(mce, cond);
4592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vbits1 = expr2vbits(mce, iftrue);
4593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vbits0 = expr2vbits(mce, iffalse);
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = typeOfIRExpr(mce->sb->tyenv, vbits0);
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mkUifU(mce, ty, assignNew('V', mce, ty,
4598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                     IRExpr_ITE(cond, vbits1, vbits0)),
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkPCastTo(mce, ty, vbitsC) );
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- This is the main expression-handling function. --------- */
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return shadow_GETI( mce, e->Iex.GetI.descr,
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  e->Iex.GetI.ix, e->Iex.GetI.bias );
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp( findShadowTmpV(mce, e->Iex.RdTmp.tmp) );
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return definedOfType(shadowTypeV(typeOfIRExpr(mce->sb->tyenv, e)));
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Qop(
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
4625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Qop.details->op,
4626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Qop.details->arg1, e->Iex.Qop.details->arg2,
4627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Qop.details->arg3, e->Iex.Qop.details->arg4
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Triop(
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
4633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Triop.details->op,
4634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Triop.details->arg1, e->Iex.Triop.details->arg2,
4635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   e->Iex.Triop.details->arg3
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Binop(
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Binop.op,
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Binop.arg1, e->Iex.Binop.arg2
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Load( mce, e->Iex.Load.end,
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      e->Iex.Load.ty,
4651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                      e->Iex.Load.addr, 0/*addr bias*/,
4652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                      NULL/* guard == "always True"*/ );
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazyN( mce, e->Iex.CCall.args,
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              e->Iex.CCall.retty,
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              e->Iex.CCall.cee );
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
4660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return expr2vbits_ITE( mce, e->Iex.ITE.cond, e->Iex.ITE.iftrue,
4661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                     e->Iex.ITE.iffalse);
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(e);
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck: expr2vbits");
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Generate shadow stmts from all kinds of IRStmts.     ---*/
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Widen a value to the host word size. */
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty, tyH;
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vatom is vbits-value and as such can only have a shadow type. */
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom));
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty  = typeOfIRExpr(mce->sb->tyenv, vatom);
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tyH = mce->hWordTy;
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tyH == Ity_I32) {
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32:
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return vatom;
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16:
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_16Uto32, vatom));
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_8Uto32, vatom));
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto unhandled;
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tyH == Ity_I64) {
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32:
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_32Uto64, vatom));
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16:
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_32Uto64,
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I32, unop(Iop_16Uto32, vatom))));
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_32Uto64,
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I32, unop(Iop_8Uto32, vatom))));
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto unhandled;
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto unhandled;
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unhandled:
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(tool_panic)("zwidenToHostWord");
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Generate a shadow store.  |addr| is always the original address
4723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   atom.  You can pass in either originals or V-bits for the data
4724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   atom, but obviously not both.  This function generates a check for
4725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   the definedness and (indirectly) the validity of |addr|, but only
4726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   when |guard| evaluates to True at run time (or is NULL).
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   |guard| :: Ity_I1 controls whether the store really happens; NULL
4729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   means it unconditionally does.  Note that |guard| itself is not
4730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   checked for definedness; the caller of this function must do that
4731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if necessary.
4732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_shadow_Store ( MCEnv* mce,
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IREndness end,
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRAtom* addr, UInt bias,
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRAtom* data, IRAtom* vdata,
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRAtom* guard )
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp     mkAdd;
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   ty, tyAddr;
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*    helper = NULL;
4743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* hname = NULL;
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* c;
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tyAddr = mce->hWordTy;
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mkAdd  = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( end == Iend_LE || end == Iend_BE );
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (data) {
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(!vdata);
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, data));
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(bias == 0);
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vdata = expr2vbits( mce, data );
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(vdata);
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,addr));
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vdata));
4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) {
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, guard));
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(typeOfIRExpr(mce->sb->tyenv, guard) == Ity_I1);
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = typeOfIRExpr(mce->sb->tyenv, vdata);
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // If we're not doing undefined value checking, pretend that this value
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // is "all valid".  That lets Vex's optimiser remove some of the V bit
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // shadow computation ops that precede it.
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 1) {
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
4775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_V256: // V256 weirdness -- used four times
4776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        c = IRConst_V256(V_BITS32_DEFINED); break;
4777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_V128: // V128 weirdness -- used twice
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        c = IRConst_V128(V_BITS16_DEFINED); break;
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I64:  c = IRConst_U64 (V_BITS64_DEFINED); break;
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32:  c = IRConst_U32 (V_BITS32_DEFINED); break;
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16:  c = IRConst_U16 (V_BITS16_DEFINED); break;
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:   c = IRConst_U8  (V_BITS8_DEFINED);  break;
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:       VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vdata = IRExpr_Const( c );
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First, emit a definedness test for the address.  This also sets
4789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      the address (shadow) to 'defined' following the test.  Both of
4790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      those actions are gated on |guard|. */
4791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   complainIfUndefined( mce, addr, guard );
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now decide which helper function to call to write the data V
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bits into shadow memory. */
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (end == Iend_LE) {
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
4797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_V256: /* we'll use the helper four times */
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_V128: /* we'll use the helper twice */
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I64: helper = &MC_(helperc_STOREV64le);
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV64le)";
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32: helper = &MC_(helperc_STOREV32le);
4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV32le)";
4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16: helper = &MC_(helperc_STOREV16le);
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV16le)";
4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:  helper = &MC_(helperc_STOREV8);
4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV8)";
4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:      VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_V128: /* we'll use the helper twice */
4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I64: helper = &MC_(helperc_STOREV64be);
4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV64be)";
4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32: helper = &MC_(helperc_STOREV32be);
4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV32be)";
4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16: helper = &MC_(helperc_STOREV16be);
4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV16be)";
4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:  helper = &MC_(helperc_STOREV8);
4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV8)";
4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
4828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Note, no V256 case here, because no big-endian target that
4829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            we support, has 256 vectors. */
4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:      VG_(tool_panic)("memcheck:do_shadow_Store(BE)");
4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (UNLIKELY(ty == Ity_V256)) {
4835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* V256-bit case -- phrased in terms of 64 bit units (Qs), with
4837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Q3 being the most significant lane. */
4838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* These are the offsets of the Qs in memory. */
4839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int     offQ0, offQ1, offQ2, offQ3;
4840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Various bits for constructing the 4 lane helper calls */
4842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRDirty *diQ0,    *diQ1,    *diQ2,    *diQ3;
4843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRAtom  *addrQ0,  *addrQ1,  *addrQ2,  *addrQ3;
4844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRAtom  *vdataQ0, *vdataQ1, *vdataQ2, *vdataQ3;
4845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRAtom  *eBiasQ0, *eBiasQ1, *eBiasQ2, *eBiasQ3;
4846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (end == Iend_LE) {
4848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         offQ0 = 0; offQ1 = 8; offQ2 = 16; offQ3 = 24;
4849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
4850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         offQ3 = 0; offQ2 = 8; offQ1 = 16; offQ0 = 24;
4851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      eBiasQ0 = tyAddr==Ity_I32 ? mkU32(bias+offQ0) : mkU64(bias+offQ0);
4854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addrQ0  = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasQ0) );
4855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vdataQ0 = assignNew('V', mce, Ity_I64, unop(Iop_V256to64_0, vdata));
4856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      diQ0    = unsafeIRDirty_0_N(
4857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   1/*regparms*/,
4858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   hname, VG_(fnptr_to_fnentry)( helper ),
4859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkIRExprVec_2( addrQ0, vdataQ0 )
4860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                );
4861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      eBiasQ1 = tyAddr==Ity_I32 ? mkU32(bias+offQ1) : mkU64(bias+offQ1);
4863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addrQ1  = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasQ1) );
4864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vdataQ1 = assignNew('V', mce, Ity_I64, unop(Iop_V256to64_1, vdata));
4865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      diQ1    = unsafeIRDirty_0_N(
4866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   1/*regparms*/,
4867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   hname, VG_(fnptr_to_fnentry)( helper ),
4868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkIRExprVec_2( addrQ1, vdataQ1 )
4869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                );
4870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      eBiasQ2 = tyAddr==Ity_I32 ? mkU32(bias+offQ2) : mkU64(bias+offQ2);
4872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addrQ2  = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasQ2) );
4873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vdataQ2 = assignNew('V', mce, Ity_I64, unop(Iop_V256to64_2, vdata));
4874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      diQ2    = unsafeIRDirty_0_N(
4875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   1/*regparms*/,
4876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   hname, VG_(fnptr_to_fnentry)( helper ),
4877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkIRExprVec_2( addrQ2, vdataQ2 )
4878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                );
4879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      eBiasQ3 = tyAddr==Ity_I32 ? mkU32(bias+offQ3) : mkU64(bias+offQ3);
4881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addrQ3  = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasQ3) );
4882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vdataQ3 = assignNew('V', mce, Ity_I64, unop(Iop_V256to64_3, vdata));
4883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      diQ3    = unsafeIRDirty_0_N(
4884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   1/*regparms*/,
4885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   hname, VG_(fnptr_to_fnentry)( helper ),
4886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mkIRExprVec_2( addrQ3, vdataQ3 )
4887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                );
4888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (guard)
4890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         diQ0->guard = diQ1->guard = diQ2->guard = diQ3->guard = guard;
4891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      setHelperAnns( mce, diQ0 );
4893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      setHelperAnns( mce, diQ1 );
4894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      setHelperAnns( mce, diQ2 );
4895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      setHelperAnns( mce, diQ3 );
4896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( 'V', mce, IRStmt_Dirty(diQ0) );
4897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( 'V', mce, IRStmt_Dirty(diQ1) );
4898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( 'V', mce, IRStmt_Dirty(diQ2) );
4899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      stmt( 'V', mce, IRStmt_Dirty(diQ3) );
4900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else if (UNLIKELY(ty == Ity_V128)) {
4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V128-bit case */
4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* See comment in next clause re 64-bit regparms */
4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* also, need to be careful about endianness */
4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     offLo64, offHi64;
4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty *diLo64, *diHi64;
4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom  *addrLo64, *addrHi64;
4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom  *vdataLo64, *vdataHi64;
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom  *eBiasLo64, *eBiasHi64;
4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (end == Iend_LE) {
4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         offLo64 = 0;
4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         offHi64 = 8;
4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         offLo64 = 8;
4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         offHi64 = 0;
4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eBiasLo64 = tyAddr==Ity_I32 ? mkU32(bias+offLo64) : mkU64(bias+offLo64);
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addrLo64  = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasLo64) );
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vdataLo64 = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, vdata));
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      diLo64    = unsafeIRDirty_0_N(
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     1/*regparms*/,
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hname, VG_(fnptr_to_fnentry)( helper ),
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkIRExprVec_2( addrLo64, vdataLo64 )
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eBiasHi64 = tyAddr==Ity_I32 ? mkU32(bias+offHi64) : mkU64(bias+offHi64);
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addrHi64  = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasHi64) );
4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vdataHi64 = assignNew('V', mce, Ity_I64, unop(Iop_V128HIto64, vdata));
4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      diHi64    = unsafeIRDirty_0_N(
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     1/*regparms*/,
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hname, VG_(fnptr_to_fnentry)( helper ),
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkIRExprVec_2( addrHi64, vdataHi64 )
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard) diLo64->guard = guard;
4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard) diHi64->guard = guard;
4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setHelperAnns( mce, diLo64 );
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setHelperAnns( mce, diHi64 );
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'V', mce, IRStmt_Dirty(diLo64) );
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'V', mce, IRStmt_Dirty(diHi64) );
4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty *di;
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom  *addrAct;
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 8/16/32/64-bit cases */
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate the actual address into addrAct. */
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bias == 0) {
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addrAct = addr;
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* eBias   = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addrAct = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBias));
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We can't do this with regparm 2 on 32-bit platforms, since
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the back ends aren't clever enough to handle 64-bit
4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparm args.  Therefore be different. */
4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         di = unsafeIRDirty_0_N(
4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 1/*regparms*/,
4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 hname, VG_(fnptr_to_fnentry)( helper ),
4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkIRExprVec_2( addrAct, vdata )
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         di = unsafeIRDirty_0_N(
4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 2/*regparms*/,
4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 hname, VG_(fnptr_to_fnentry)( helper ),
4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkIRExprVec_2( addrAct,
4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                zwidenToHostWord( mce, vdata ))
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard) di->guard = guard;
4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setHelperAnns( mce, di );
4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'V', mce, IRStmt_Dirty(di) );
4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do lazy pessimistic propagation through a dirty helper call, by
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   looking at the annotations on it.  This is the most complex part of
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Memcheck. */
4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRType szToITy ( Int n )
4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (n) {
4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return Ity_I8;
4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return Ity_I16;
4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return Ity_I32;
4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return Ity_I64;
4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: VG_(tool_panic)("szToITy(memcheck)");
4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int       i, k, n, toDo, gSz, gOff;
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom    *src, *here, *curr;
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType    tySrc, tyDst;
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp    dst;
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IREndness end;
5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* What's the native endianness?  We need to know this. */
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VG_BIGENDIAN)
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end = Iend_BE;
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VG_LITTLEENDIAN)
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end = Iend_LE;
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#    error "Unknown endianness"
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First check the guard. */
5018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   complainIfUndefined(mce, d->guard, NULL);
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now round up all inputs and PCast over them. */
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   curr = definedOfType(Ity_I32);
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Inputs: unmasked args
5024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Note: arguments are evaluated REGARDLESS of the guard expression */
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; d->args[i]; i++) {
5026436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom* arg = d->args[i];
5027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if ( (d->cee->mcx_mask & (1<<i))
5028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           || UNLIKELY(is_IRExpr_VECRET_or_BBPTR(arg)) ) {
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ignore this arg */
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5031436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, arg) );
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = mkUifU32(mce, here, curr);
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: guest state that we read. */
5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < d->nFxState; i++) {
5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->fxState[i].fx != Ifx_None);
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->fxState[i].fx == Ifx_Write)
5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Enumerate the described state segments */
5043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (k = 0; k < 1 + d->fxState[i].nRepeats; k++) {
5044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gOff = d->fxState[i].offset + k * d->fxState[i].repeatLen;
5045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gSz  = d->fxState[i].size;
5046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Ignore any sections marked as 'always defined'. */
5048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (isAlwaysDefd(mce, gOff, gSz)) {
5049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0)
5050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
5051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        gOff, gSz);
5052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            continue;
5053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
5054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* This state element is read or modified.  So we need to
5056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            consider it.  If larger than 8 bytes, deal with it in
5057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            8-byte chunks. */
5058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         while (True) {
5059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            tl_assert(gSz >= 0);
5060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (gSz == 0) break;
5061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            n = gSz <= 8 ? gSz : 8;
5062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* update 'curr' with UifU of the state slice
5063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gOff .. gOff+n-1 */
5064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            tySrc = szToITy( n );
5065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Observe the guard expression. If it is false use an
5067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               all-bits-defined bit pattern */
5068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRAtom *cond, *iffalse, *iftrue;
5069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5070436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            cond    = assignNew('V', mce, Ity_I1, d->guard);
5071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iftrue  = assignNew('V', mce, tySrc, shadow_GET(mce, gOff, tySrc));
5072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iffalse = assignNew('V', mce, tySrc, definedOfType(tySrc));
5073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            src     = assignNew('V', mce, tySrc,
5074436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                IRExpr_ITE(cond, iftrue, iffalse));
5075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            here = mkPCastTo( mce, Ity_I32, src );
5077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            curr = mkUifU32(mce, here, curr);
5078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gSz -= n;
5079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gOff += n;
5080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
5081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: memory.  First set up some info needed regardless of
5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      whether we're doing reads or writes. */
5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx != Ifx_None) {
5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Because we may do multiple shadow loads/stores from the same
5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base address, it's best to do a single test of its
5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         definedness right now.  Post-instrumentation optimisation
5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         should remove all but this test. */
5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType tyAddr;
5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->mAddr);
5094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      complainIfUndefined(mce, d->mAddr, d->guard);
5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tyAddr = typeOfIRExpr(mce->sb->tyenv, d->mAddr);
5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(tyAddr == mce->hWordTy); /* not really right */
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with memory inputs (reads or modifies) */
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toDo   = d->mSize;
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 32-bit chunks.  We don't care about the endianness
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         since it's all going to be condensed down to a single bit,
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         but nevertheless choose an endianness which is hopefully
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         native to the platform. */
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 4) {
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = mkPCastTo(
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce, Ity_I32,
5111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   expr2vbits_Load_guarded_Simple(
5112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      mce, end, Ity_I32, d->mAddr, d->mSize - toDo, d->guard )
5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = mkUifU32(mce, here, curr);
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 4;
5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 16-bit chunks */
5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 2) {
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = mkPCastTo(
5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce, Ity_I32,
5121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   expr2vbits_Load_guarded_Simple(
5122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      mce, end, Ity_I16, d->mAddr, d->mSize - toDo, d->guard )
5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = mkUifU32(mce, here, curr);
5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 2;
5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* chew off the remaining 8-bit chunk, if any */
5128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (toDo == 1) {
5129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         here = mkPCastTo(
5130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   mce, Ity_I32,
5131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   expr2vbits_Load_guarded_Simple(
5132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      mce, end, Ity_I8, d->mAddr, d->mSize - toDo, d->guard )
5133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                );
5134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         curr = mkUifU32(mce, here, curr);
5135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         toDo -= 1;
5136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      tl_assert(toDo == 0);
5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Whew!  So curr is a 32-bit V-value summarising pessimistically
5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      all the inputs to the helper.  Now we need to re-distribute the
5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      results to all destinations. */
5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: the destination temporary, if there is one. */
5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->tmp != IRTemp_INVALID) {
5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst   = findShadowTmpV(mce, d->tmp);
5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tyDst = typeOfIRTemp(mce->sb->tyenv, d->tmp);
5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'V', mce, dst, mkPCastTo( mce, tyDst, curr) );
5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: guest state that we write or modify. */
5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < d->nFxState; i++) {
5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->fxState[i].fx != Ifx_None);
5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->fxState[i].fx == Ifx_Read)
5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Enumerate the described state segments */
5158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (k = 0; k < 1 + d->fxState[i].nRepeats; k++) {
5159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gOff = d->fxState[i].offset + k * d->fxState[i].repeatLen;
5160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gSz  = d->fxState[i].size;
5161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Ignore any sections marked as 'always defined'. */
5163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (isAlwaysDefd(mce, gOff, gSz))
5164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            continue;
5165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* This state element is written or modified.  So we need to
5167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            consider it.  If larger than 8 bytes, deal with it in
5168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            8-byte chunks. */
5169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         while (True) {
5170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            tl_assert(gSz >= 0);
5171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (gSz == 0) break;
5172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            n = gSz <= 8 ? gSz : 8;
5173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Write suitably-casted 'curr' to the state slice
5174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gOff .. gOff+n-1 */
5175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            tyDst = szToITy( n );
5176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do_shadow_PUT( mce, gOff,
5177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                NULL, /* original atom */
5178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkPCastTo( mce, tyDst, curr ), d->guard );
5179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gSz -= n;
5180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gOff += n;
5181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: memory that we write or modify.  Same comments about
5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      endianness as above apply. */
5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toDo   = d->mSize;
5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 32-bit chunks */
5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 4) {
5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          NULL, /* original data */
5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkPCastTo( mce, Ity_I32, curr ),
5194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          d->guard );
5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 4;
5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 16-bit chunks */
5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 2) {
5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          NULL, /* original data */
5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkPCastTo( mce, Ity_I16, curr ),
5202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          d->guard );
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 2;
5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* chew off the remaining 8-bit chunk, if any */
5206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (toDo == 1) {
5207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
5208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          NULL, /* original data */
5209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          mkPCastTo( mce, Ity_I8, curr ),
5210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          d->guard );
5211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         toDo -= 1;
5212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      tl_assert(toDo == 0);
5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* We have an ABI hint telling us that [base .. base+len-1] is to
5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   become undefined ("writable").  Generate code to call a helper to
5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notify the A/V bit machinery of this fact.
5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We call
5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len,
5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    Addr nia );
5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_AbiHint ( MCEnv* mce, IRExpr* base, Int len, IRExpr* nia )
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Minor optimisation: if not doing origin tracking, ignore the
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      supplied nia and pass zero instead.  This is on the basis that
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(helperc_MAKE_STACK_UNINIT) will ignore it anyway, and we can
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      almost always generate a shorter instruction to put zero into a
5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register than any other value. */
5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) < 3)
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nia = mkIRExpr_HWord(0);
5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_0_N(
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           0/*regparms*/,
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "MC_(helperc_MAKE_STACK_UNINIT)",
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           VG_(fnptr_to_fnentry)( &MC_(helperc_MAKE_STACK_UNINIT) ),
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           mkIRExprVec_3( base, mkIRExpr_HWord( (UInt)len), nia )
5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'V', mce, IRStmt_Dirty(di) );
5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ Dealing with IRCAS (big and complex) ------ */
5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* FWDS */
5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* gen_load_b  ( MCEnv* mce, Int szB,
5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* baseaddr, Int offset );
5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* gen_maxU32  ( MCEnv* mce, IRAtom* b1, IRAtom* b2 );
5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void    gen_store_b ( MCEnv* mce, Int szB,
5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* baseaddr, Int offset, IRAtom* dataB,
5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* guard );
5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_CAS_single ( MCEnv* mce, IRCAS* cas );
5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_CAS_double ( MCEnv* mce, IRCAS* cas );
5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Either ORIG and SHADOW are both IRExpr.RdTmps, or they are both
5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr.Consts, else this asserts.  If they are both Consts, it
5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   doesn't do anything.  So that just leaves the RdTmp case.
5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In which case: this assigns the shadow value SHADOW to the IR
5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shadow temporary associated with ORIG.  That is, ORIG, being an
5269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   original temporary, will have a shadow temporary associated with
5270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it.  However, in the case envisaged here, there will so far have
5271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   been no IR emitted to actually write a shadow value into that
5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   temporary.  What this routine does is to (emit IR to) copy the
5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value in SHADOW into said temporary, so that after this call,
5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr.RdTmps of ORIG's shadow temp will correctly pick up the
5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value in SHADOW.
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Point is to allow callers to compute "by hand" a shadow value for
5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ORIG, and force it to be associated with ORIG.
5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   How do we know that that shadow associated with ORIG has not so far
5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   been assigned to?  Well, we don't per se know that, but supposing
5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it had.  Then this routine would create a second assignment to it,
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and later the IR sanity checker would barf.  But that never
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   happens.  QED.
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bind_shadow_tmp_to_orig ( UChar how,
5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      MCEnv* mce,
5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      IRAtom* orig, IRAtom* shadow )
5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, orig));
5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, shadow));
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (orig->tag) {
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(shadow->tag == Iex_Const);
5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(shadow->tag == Iex_RdTmp);
5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (how == 'V') {
5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign('V', mce, findShadowTmpV(mce,orig->Iex.RdTmp.tmp),
5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   shadow);
5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(how == 'B');
5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign('B', mce, findShadowTmpB(mce,orig->Iex.RdTmp.tmp),
5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   shadow);
5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_shadow_CAS ( MCEnv* mce, IRCAS* cas )
5315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scheme is (both single- and double- cases):
5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      1. fetch data#,dataB (the proposed new value)
5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      2. fetch expd#,expdB (what we expect to see at the address)
5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      3. check definedness of address
5323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      4. load old#,oldB from shadow memory; this also checks
5325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addressibility of the address
5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      5. the CAS itself
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      6. compute "expected == old".  See COMMENT_ON_CasCmpEQ below.
5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      7. if "expected == old" (as computed by (6))
5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            store data#,dataB to shadow memory
5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Note that 5 reads 'old' but 4 reads 'old#'.  Similarly, 5 stores
5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'data' but 7 stores 'data#'.  Hence it is possible for the
5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shadow data to be incorrectly checked and/or updated:
5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * 7 is at least gated correctly, since the 'expected == old'
5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        condition is derived from outputs of 5.  However, the shadow
5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        write could happen too late: imagine after 5 we are
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        descheduled, a different thread runs, writes a different
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (shadow) value at the address, and then we resume, hence
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        overwriting the shadow value written by the other thread.
5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Because the original memory access is atomic, there's no way to
5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      make both the original and shadow accesses into a single atomic
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thing, hence this is unavoidable.
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      At least as Valgrind stands, I don't think it's a problem, since
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      we're single threaded *and* we guarantee that there are no
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      context switches during the execution of any specific superblock
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      -- context switches can only happen at superblock boundaries.
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If Valgrind ever becomes MT in the future, then it might be more
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of a problem.  A possible kludge would be to artificially
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      associate with the location, a lock, which we must acquire and
5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      release around the transaction as a whole.  Hmm, that probably
5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      would't work properly since it only guards us against other
5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      threads doing CASs on the same location, not against other
5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      threads doing normal reads and writes.
5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ------------------------------------------------------------
5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      COMMENT_ON_CasCmpEQ:
5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Note two things.  Firstly, in the sequence above, we compute
5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "expected == old", but we don't check definedness of it.  Why
5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not?  Also, the x86 and amd64 front ends use
5369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Iop_CasCmp{EQ,NE}{8,16,32,64} comparisons to make the equivalent
5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      determination (expected == old ?) for themselves, and we also
5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      don't check definedness for those primops; we just say that the
5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      result is defined.  Why?  Details follow.
5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      x86/amd64 contains various forms of locked insns:
5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * lock prefix before all basic arithmetic insn;
5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        eg lock xorl %reg1,(%reg2)
5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * atomic exchange reg-mem
5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * compare-and-swaps
5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Rather than attempt to represent them all, which would be a
5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      royal PITA, I used a result from Maurice Herlihy
5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (http://en.wikipedia.org/wiki/Maurice_Herlihy), in which he
5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      demonstrates that compare-and-swap is a primitive more general
5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      than the other two, and so can be used to represent all of them.
5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      So the translation scheme for (eg) lock incl (%reg) is as
5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      follows:
5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        again:
5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         old = * %reg
5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         new = old + 1
5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         atomically { if (* %reg == old) { * %reg = new } else { goto again } }
5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The "atomically" is the CAS bit.  The scheme is always the same:
5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      get old value from memory, compute new value, atomically stuff
5395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new value back in memory iff the old value has not changed (iow,
5396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      no other thread modified it in the meantime).  If it has changed
5397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      then we've been out-raced and we have to start over.
5398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Now that's all very neat, but it has the bad side effect of
5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      introducing an explicit equality test into the translation.
5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Consider the behaviour of said code on a memory location which
5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is uninitialised.  We will wind up doing a comparison on
5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uninitialised data, and mc duly complains.
5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      What's difficult about this is, the common case is that the
5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      location is uncontended, and so we're usually comparing the same
5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      value (* %reg) with itself.  So we shouldn't complain even if it
5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is undefined.  But mc doesn't know that.
5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      My solution is to mark the == in the IR specially, so as to tell
5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mc that it almost certainly compares a value with itself, and we
5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      should just regard the result as always defined.  Rather than
5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add a bit to all IROps, I just cloned Iop_CmpEQ{8,16,32,64} into
5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Iop_CasCmpEQ{8,16,32,64} so as not to disturb anything else.
5415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      So there's always the question of, can this give a false
5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      negative?  eg, imagine that initially, * %reg is defined; and we
5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      read that; but then in the gap between the read and the CAS, a
5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      different thread writes an undefined (and different) value at
5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the location.  Then the CAS in this thread will fail and we will
5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      go back to "again:", but without knowing that the trip back
5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      there was based on an undefined comparison.  No matter; at least
5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the other thread won the race and the location is correctly
5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      marked as undefined.  What if it wrote an uninitialised version
5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of the same value that was there originally, though?
5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      etc etc.  Seems like there's a small corner case in which we
5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      might lose the fact that something's defined -- we're out-raced
5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in between the "old = * reg" and the "atomically {", _and_ the
5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      other thread is writing in an undefined version of what's
5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      already there.  Well, that seems pretty unlikely.
5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ---
5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If we ever need to reinstate it .. code which generates a
5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      definedness test for "expected == old" was removed at r10432 of
5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this file.
5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cas->oldHi == IRTemp_INVALID) {
5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_shadow_CAS_single( mce, cas );
5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_shadow_CAS_double( mce, cas );
5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_CAS_single ( MCEnv* mce, IRCAS* cas )
5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vdataLo = NULL, *bdataLo = NULL;
5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vexpdLo = NULL, *bexpdLo = NULL;
5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *voldLo  = NULL, *boldLo  = NULL;
5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *expd_eq_old = NULL;
5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opCasCmpEQ;
5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    elemSzB;
5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType elemTy;
5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   otrak = MC_(clo_mc_level) >= 3; /* a shorthand */
5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* single CAS */
5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->oldHi == IRTemp_INVALID);
5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->expdHi == NULL);
5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->dataHi == NULL);
5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   elemTy = typeOfIRExpr(mce->sb->tyenv, cas->expdLo);
5464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (elemTy) {
5465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  elemSzB = 1; opCasCmpEQ = Iop_CasCmpEQ8;  break;
5466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: elemSzB = 2; opCasCmpEQ = Iop_CasCmpEQ16; break;
5467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: elemSzB = 4; opCasCmpEQ = Iop_CasCmpEQ32; break;
5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: elemSzB = 8; opCasCmpEQ = Iop_CasCmpEQ64; break;
5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: tl_assert(0); /* IR defn disallows any other types */
5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 1. fetch data# (the proposed new value) */
5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->dataLo));
5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vdataLo
5475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->dataLo));
5476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vdataLo));
5477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
5478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bdataLo
5479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->dataLo));
5480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bdataLo));
5481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 2. fetch expected# (what we expect to see at the address) */
5484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->expdLo));
5485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vexpdLo
5486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->expdLo));
5487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vexpdLo));
5488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
5489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bexpdLo
5490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->expdLo));
5491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bexpdLo));
5492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 3. check definedness of address */
5495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 4. fetch old# from shadow memory; this also checks
5496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addressibility of the address */
5497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   voldLo
5498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew(
5499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           'V', mce, elemTy,
5500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           expr2vbits_Load(
5501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mce,
5502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              cas->end, elemTy, cas->addr, 0/*Addr bias*/,
5503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              NULL/*always happens*/
5504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ));
5505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bind_shadow_tmp_to_orig('V', mce, mkexpr(cas->oldLo), voldLo);
5506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
5507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      boldLo
5508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32,
5509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     gen_load_b(mce, elemSzB, cas->addr, 0/*addr bias*/));
5510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bind_shadow_tmp_to_orig('B', mce, mkexpr(cas->oldLo), boldLo);
5511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 5. the CAS itself */
5514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'C', mce, IRStmt_CAS(cas) );
5515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 6. compute "expected == old" */
5517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* See COMMENT_ON_CasCmpEQ in this file background/rationale. */
5518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note that 'C' is kinda faking it; it is indeed a non-shadow
5519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tree, but it's not copied from the input block. */
5520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expd_eq_old
5521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('C', mce, Ity_I1,
5522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(opCasCmpEQ, cas->expdLo, mkexpr(cas->oldLo)));
5523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 7. if "expected == old"
5525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            store data# to shadow memory */
5526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_shadow_Store( mce, cas->end, cas->addr, 0/*bias*/,
5527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    NULL/*data*/, vdataLo/*vdata*/,
5528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expd_eq_old/*guard for store*/ );
5529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
5530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gen_store_b( mce, elemSzB, cas->addr, 0/*offset*/,
5531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   bdataLo/*bdata*/,
5532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expd_eq_old/*guard for store*/ );
5533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_CAS_double ( MCEnv* mce, IRCAS* cas )
5538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vdataHi = NULL, *bdataHi = NULL;
5540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vdataLo = NULL, *bdataLo = NULL;
5541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vexpdHi = NULL, *bexpdHi = NULL;
5542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vexpdLo = NULL, *bexpdLo = NULL;
5543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *voldHi  = NULL, *boldHi  = NULL;
5544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *voldLo  = NULL, *boldLo  = NULL;
5545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *xHi = NULL, *xLo = NULL, *xHL = NULL;
5546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *expd_eq_old = NULL, *zero = NULL;
5547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opCasCmpEQ, opOr, opXor;
5548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    elemSzB, memOffsLo, memOffsHi;
5549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType elemTy;
5550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   otrak = MC_(clo_mc_level) >= 3; /* a shorthand */
5551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* double CAS */
5553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->oldHi != IRTemp_INVALID);
5554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->expdHi != NULL);
5555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->dataHi != NULL);
5556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   elemTy = typeOfIRExpr(mce->sb->tyenv, cas->expdLo);
5558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (elemTy) {
5559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
5560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCasCmpEQ = Iop_CasCmpEQ8; opOr = Iop_Or8; opXor = Iop_Xor8;
5561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         elemSzB = 1; zero = mkU8(0);
5562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
5564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCasCmpEQ = Iop_CasCmpEQ16; opOr = Iop_Or16; opXor = Iop_Xor16;
5565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         elemSzB = 2; zero = mkU16(0);
5566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
5568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCasCmpEQ = Iop_CasCmpEQ32; opOr = Iop_Or32; opXor = Iop_Xor32;
5569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         elemSzB = 4; zero = mkU32(0);
5570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
5572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCasCmpEQ = Iop_CasCmpEQ64; opOr = Iop_Or64; opXor = Iop_Xor64;
5573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         elemSzB = 8; zero = mkU64(0);
5574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0); /* IR defn disallows any other types */
5577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 1. fetch data# (the proposed new value) */
5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->dataHi));
5581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->dataLo));
5582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vdataHi
5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->dataHi));
5584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vdataLo
5585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->dataLo));
5586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vdataHi));
5587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vdataLo));
5588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
5589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bdataHi
5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->dataHi));
5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bdataLo
5592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->dataLo));
5593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bdataHi));
5594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bdataLo));
5595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 2. fetch expected# (what we expect to see at the address) */
5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->expdHi));
5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->expdLo));
5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vexpdHi
5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->expdHi));
5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vexpdLo
5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->expdLo));
5604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vexpdHi));
5605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vexpdLo));
5606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
5607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bexpdHi
5608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->expdHi));
5609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bexpdLo
5610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->expdLo));
5611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bexpdHi));
5612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bexpdLo));
5613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 3. check definedness of address */
5616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 4. fetch old# from shadow memory; this also checks
5617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addressibility of the address */
5618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cas->end == Iend_LE) {
5619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memOffsLo = 0;
5620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memOffsHi = elemSzB;
5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(cas->end == Iend_BE);
5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memOffsLo = elemSzB;
5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memOffsHi = 0;
5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   voldHi
5627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew(
5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           'V', mce, elemTy,
5629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           expr2vbits_Load(
5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mce,
5631436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              cas->end, elemTy, cas->addr, memOffsHi/*Addr bias*/,
5632436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              NULL/*always happens*/
5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ));
5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   voldLo
5635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew(
5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           'V', mce, elemTy,
5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           expr2vbits_Load(
5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mce,
5639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              cas->end, elemTy, cas->addr, memOffsLo/*Addr bias*/,
5640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              NULL/*always happens*/
5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ));
5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bind_shadow_tmp_to_orig('V', mce, mkexpr(cas->oldHi), voldHi);
5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bind_shadow_tmp_to_orig('V', mce, mkexpr(cas->oldLo), voldLo);
5644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      boldHi
5646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32,
5647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     gen_load_b(mce, elemSzB, cas->addr,
5648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                memOffsHi/*addr bias*/));
5649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      boldLo
5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32,
5651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     gen_load_b(mce, elemSzB, cas->addr,
5652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                memOffsLo/*addr bias*/));
5653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bind_shadow_tmp_to_orig('B', mce, mkexpr(cas->oldHi), boldHi);
5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bind_shadow_tmp_to_orig('B', mce, mkexpr(cas->oldLo), boldLo);
5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 5. the CAS itself */
5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'C', mce, IRStmt_CAS(cas) );
5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 6. compute "expected == old" */
5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* See COMMENT_ON_CasCmpEQ in this file background/rationale. */
5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note that 'C' is kinda faking it; it is indeed a non-shadow
5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tree, but it's not copied from the input block. */
5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xHi = oldHi ^ expdHi;
5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xLo = oldLo ^ expdLo;
5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xHL = xHi | xLo;
5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expd_eq_old = xHL == 0;
5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xHi = assignNew('C', mce, elemTy,
5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(opXor, cas->expdHi, mkexpr(cas->oldHi)));
5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xLo = assignNew('C', mce, elemTy,
5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(opXor, cas->expdLo, mkexpr(cas->oldLo)));
5674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xHL = assignNew('C', mce, elemTy,
5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(opOr, xHi, xLo));
5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expd_eq_old
5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('C', mce, Ity_I1,
5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(opCasCmpEQ, xHL, zero));
5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 7. if "expected == old"
5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            store data# to shadow memory */
5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_shadow_Store( mce, cas->end, cas->addr, memOffsHi/*bias*/,
5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    NULL/*data*/, vdataHi/*vdata*/,
5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expd_eq_old/*guard for store*/ );
5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_shadow_Store( mce, cas->end, cas->addr, memOffsLo/*bias*/,
5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    NULL/*data*/, vdataLo/*vdata*/,
5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expd_eq_old/*guard for store*/ );
5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
5689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gen_store_b( mce, elemSzB, cas->addr, memOffsHi/*offset*/,
5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   bdataHi/*bdata*/,
5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expd_eq_old/*guard for store*/ );
5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gen_store_b( mce, elemSzB, cas->addr, memOffsLo/*offset*/,
5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   bdataLo/*bdata*/,
5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expd_eq_old/*guard for store*/ );
5695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ Dealing with LL/SC (not difficult) ------ */
5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_LLSC ( MCEnv*    mce,
5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IREndness stEnd,
5703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp    stResult,
5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr*   stAddr,
5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr*   stStoredata )
5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* In short: treat a load-linked like a normal load followed by an
5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignment of the loaded (shadow) data to the result temporary.
5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Treat a store-conditional like a normal store, and mark the
5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      result temporary as defined. */
5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType resTy  = typeOfIRTemp(mce->sb->tyenv, stResult);
5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp resTmp = findShadowTmpV(mce, stResult);
5713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(stAddr));
5715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (stStoredata)
5716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isIRAtom(stStoredata));
5717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (stStoredata == NULL) {
5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Load Linked */
5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Just treat this as a normal load, followed by an assignment of
5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the value to .result. */
5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Stay sane */
5723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(resTy == Ity_I64 || resTy == Ity_I32
5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || resTy == Ity_I16 || resTy == Ity_I8);
5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'V', mce, resTmp,
5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expr2vbits_Load(
5727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      mce, stEnd, resTy, stAddr, 0/*addr bias*/,
5728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      NULL/*always happens*/) );
5729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Store Conditional */
5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Stay sane */
5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType dataTy = typeOfIRExpr(mce->sb->tyenv,
5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   stStoredata);
5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(dataTy == Ity_I64 || dataTy == Ity_I32
5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || dataTy == Ity_I16 || dataTy == Ity_I8);
5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_shadow_Store( mce, stEnd,
5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            stAddr, 0/* addr bias */,
5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            stStoredata,
5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            NULL /* shadow data */,
5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            NULL/*guard*/ );
5741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is a store conditional, so it writes to .result a value
5742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         indicating whether or not the store succeeded.  Just claim
5743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this value is always defined.  In the PowerPC interpretation
5744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of store-conditional, definedness of the success indication
5745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         depends on whether the address of the store matches the
5746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reservation address.  But we can't tell that here (and
5747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         anyway, we're not being PowerPC-specific).  At least we are
5748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         guaranteed that the definedness of the store address, and its
5749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addressibility, will be checked as per normal.  So it seems
5750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pretty safe to just say that the success indication is always
5751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         defined.
5752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         In schemeS, for origin tracking, we must correspondingly set
5754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         a no-origin value for the origin shadow of .result.
5755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
5756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(resTy == Ity_I1);
5757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'V', mce, resTmp, definedOfType(resTy) );
5758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* ---- Dealing with LoadG/StoreG (not entirely simple) ---- */
5763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void do_shadow_StoreG ( MCEnv* mce, IRStoreG* sg )
5765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
5766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   complainIfUndefined(mce, sg->guard, NULL);
5767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* do_shadow_Store will generate code to check the definedness and
5768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      validity of sg->addr, in the case where sg->guard evaluates to
5769436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      True at run-time. */
5770436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   do_shadow_Store( mce, sg->end,
5771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    sg->addr, 0/* addr bias */,
5772436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    sg->data,
5773436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    NULL /* shadow data */,
5774436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    sg->guard );
5775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
5776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void do_shadow_LoadG ( MCEnv* mce, IRLoadG* lg )
5778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
5779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   complainIfUndefined(mce, lg->guard, NULL);
5780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* expr2vbits_Load_guarded_General will generate code to check the
5781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      definedness and validity of lg->addr, in the case where
5782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      lg->guard evaluates to True at run-time. */
5783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Look at the LoadG's built-in conversion operation, to determine
5785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      the source (actual loaded data) type, and the equivalent IROp.
5786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      NOTE that implicitly we are taking a widening operation to be
5787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      applied to original atoms and producing one that applies to V
5788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      bits.  Since signed and unsigned widening are self-shadowing,
5789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      this is a straight copy of the op (modulo swapping from the
5790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRLoadGOp form to the IROp form).  Note also therefore that this
5791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      implicitly duplicates the logic to do with said widening ops in
5792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      expr2vbits_Unop.  See comment at the start of expr2vbits_Unop. */
5793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IROp   vwiden   = Iop_INVALID;
5794436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRType loadedTy = Ity_INVALID;
5795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (lg->cvt) {
5796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_Ident32: loadedTy = Ity_I32; vwiden = Iop_INVALID; break;
5797436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_16Uto32: loadedTy = Ity_I16; vwiden = Iop_16Uto32; break;
5798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_16Sto32: loadedTy = Ity_I16; vwiden = Iop_16Sto32; break;
5799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_8Uto32:  loadedTy = Ity_I8;  vwiden = Iop_8Uto32;  break;
5800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_8Sto32:  loadedTy = Ity_I8;  vwiden = Iop_8Sto32;  break;
5801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default: VG_(tool_panic)("do_shadow_LoadG");
5802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
5803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* vbits_alt
5805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = expr2vbits( mce, lg->alt );
5806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* vbits_final
5807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = expr2vbits_Load_guarded_General(mce, lg->end, loadedTy,
5808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        lg->addr, 0/*addr bias*/,
5809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        lg->guard, vwiden, vbits_alt );
5810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* And finally, bind the V bits to the destination temporary. */
5811436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   assign( 'V', mce, findShadowTmpV(mce, lg->dst), vbits_final );
5812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
5813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5814436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
5816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Memcheck main                                        ---*/
5817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
5818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void schemeS ( MCEnv* mce, IRStmt* st );
5820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isBogusAtom ( IRAtom* at )
5822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong n = 0;
5824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* con;
5825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(at));
5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (at->tag == Iex_RdTmp)
5827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(at->tag == Iex_Const);
5829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   con = at->Iex.Const.con;
5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (con->tag) {
5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U1:   return False;
5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U8:   n = (ULong)con->Ico.U8; break;
5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U16:  n = (ULong)con->Ico.U16; break;
5834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U32:  n = (ULong)con->Ico.U32; break;
5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U64:  n = (ULong)con->Ico.U64; break;
5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_F64:  return False;
5837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ico_F32i: return False;
5838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_F64i: return False;
5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_V128: return False;
5840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ico_V256: return False;
5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: ppIRExpr(at); tl_assert(0);
5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VG_(printf)("%llx\n", n); */
5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (/*32*/    n == 0xFEFEFEFFULL
5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*32*/ || n == 0x80808080ULL
5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*32*/ || n == 0x7F7F7F7FULL
5847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           /*32*/ || n == 0x7EFEFEFFULL
5848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           /*32*/ || n == 0x81010100ULL
5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0xFFFFFFFFFEFEFEFFULL
5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0xFEFEFEFEFEFEFEFFULL
5851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0x0000000000008080ULL
5852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0x8080808080808080ULL
5853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0x0101010101010101ULL
5854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          );
5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*  e;
5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e = st->Ist.WrTmp.data;
5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->tag) {
5867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Get:
5868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_RdTmp:
5869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Const:
5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e);
5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Unop:
5873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return isBogusAtom(e->Iex.Unop.arg)
5874436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      || e->Iex.Unop.op == Iop_GetMSBs8x16;
5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_GetI:
5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.GetI.ix);
5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Binop:
5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.Binop.arg1)
5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || isBogusAtom(e->Iex.Binop.arg2);
5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Triop:
5881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return isBogusAtom(e->Iex.Triop.details->arg1)
5882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      || isBogusAtom(e->Iex.Triop.details->arg2)
5883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      || isBogusAtom(e->Iex.Triop.details->arg3);
5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Qop:
5885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return isBogusAtom(e->Iex.Qop.details->arg1)
5886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      || isBogusAtom(e->Iex.Qop.details->arg2)
5887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      || isBogusAtom(e->Iex.Qop.details->arg3)
5888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      || isBogusAtom(e->Iex.Qop.details->arg4);
5889436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iex_ITE:
5890436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return isBogusAtom(e->Iex.ITE.cond)
5891436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      || isBogusAtom(e->Iex.ITE.iftrue)
5892436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      || isBogusAtom(e->Iex.ITE.iffalse);
5893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Load:
5894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.Load.addr);
5895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_CCall:
5896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (i = 0; e->Iex.CCall.args[i]; i++)
5897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (isBogusAtom(e->Iex.CCall.args[i]))
5898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return True;
5899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto unhandled;
5902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
5904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
5905436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         for (i = 0; d->args[i]; i++) {
5906436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRAtom* atom = d->args[i];
5907436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(atom))) {
5908436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (isBogusAtom(atom))
5909436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  return True;
5910436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
5911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
5912436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (isBogusAtom(d->guard))
5913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
5914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mAddr && isBogusAtom(d->mAddr))
5915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
5916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
5918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.Put.data);
5919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
5920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return isBogusAtom(st->Ist.PutI.details->ix)
5921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                || isBogusAtom(st->Ist.PutI.details->data);
5922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
5923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.Store.addr)
5924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || isBogusAtom(st->Ist.Store.data);
5925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG: {
5926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRStoreG* sg = st->Ist.StoreG.details;
5927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return isBogusAtom(sg->addr) || isBogusAtom(sg->data)
5928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                || isBogusAtom(sg->guard);
5929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
5930436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG: {
5931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRLoadG* lg = st->Ist.LoadG.details;
5932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return isBogusAtom(lg->addr) || isBogusAtom(lg->alt)
5933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                || isBogusAtom(lg->guard);
5934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
5935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
5936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.Exit.guard);
5937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
5938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.AbiHint.base)
5939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || isBogusAtom(st->Ist.AbiHint.nia);
5940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
5941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
5942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
5943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
5945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
5946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(cas->addr)
5947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || (cas->expdHi ? isBogusAtom(cas->expdHi) : False)
5948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || isBogusAtom(cas->expdLo)
5949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || (cas->dataHi ? isBogusAtom(cas->dataHi) : False)
5950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || isBogusAtom(cas->dataLo);
5951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
5952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.LLSC.addr)
5953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || (st->Ist.LLSC.storedata
5954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ? isBogusAtom(st->Ist.LLSC.storedata)
5955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       : False);
5956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unhandled:
5958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
5959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("hasBogusLiterals");
5960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* MC_(instrument) ( VgCallbackClosure* closure,
5965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRSB* sb_in,
5966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        VexGuestLayout* layout,
5967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        VexGuestExtents* vge,
5968436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        VexArchInfo* archinfo_host,
5969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRType gWordTy, IRType hWordTy )
5970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    verboze = 0||False;
5972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    bogus;
5973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, j, first_stmt;
5974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
5975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MCEnv   mce;
5976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB*   sb_out;
5977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (gWordTy != hWordTy) {
5979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We don't currently support this case. */
5980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(tool_panic)("host/guest word size mismatch");
5981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check we're not completely nuts */
5984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(UWord)  == sizeof(void*));
5985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Word)   == sizeof(void*));
5986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Addr)   == sizeof(void*));
5987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(ULong)  == 8);
5988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Long)   == 8);
5989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Addr64) == 8);
5990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(UInt)   == 4);
5991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Int)    == 4);
5992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(MC_(clo_mc_level) >= 1 && MC_(clo_mc_level) <= 3);
5994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up SB */
5996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sb_out = deepCopyIRSBExceptStmts(sb_in);
5997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up the running environment.  Both .sb and .tmpMap are
5999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      modified as we go along.  Note that tmps are added to both
6000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .sb->tyenv and .tmpMap together, so the valid index-set for
6001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      those two arrays should always be identical. */
6002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(&mce, 0, sizeof(mce));
6003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.sb             = sb_out;
6004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.trace          = verboze;
6005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.layout         = layout;
6006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.hWordTy        = hWordTy;
6007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.bogusLiterals  = False;
6008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Do expensive interpretation for Iop_Add32 and Iop_Add64 on
6010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Darwin.  10.7 is mostly built with LLVM, which uses these for
6011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      bitfield inserts, and we get a lot of false errors if the cheap
6012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      interpretation is used, alas.  Could solve this much better if
6013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      we knew which of such adds came from x86/amd64 LEA instructions,
6014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      since these are the only ones really needing the expensive
6015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      interpretation, but that would require some way to tag them in
6016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the _toIR.c front ends, which is a lot of faffing around.  So
6017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for now just use the slow and blunt-instrument solution. */
6018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   mce.useLLVMworkarounds = False;
6019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  if defined(VGO_darwin)
6020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   mce.useLLVMworkarounds = True;
6021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  endif
6022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.tmpMap = VG_(newXA)( VG_(malloc), "mc.MC_(instrument).1", VG_(free),
6024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            sizeof(TempMapEnt));
6025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < sb_in->tyenv->types_used; i++) {
6026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TempMapEnt ent;
6027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent.kind    = Orig;
6028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent.shadowV = IRTemp_INVALID;
6029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent.shadowB = IRTemp_INVALID;
6030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(addToXA)( mce.tmpMap, &ent );
6031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( VG_(sizeXA)( mce.tmpMap ) == sb_in->tyenv->types_used );
6033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make a preliminary inspection of the statements, to see if there
6035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      are any dodgy-looking literals.  If there are, we generate
6036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      extra-detailed (hence extra-expensive) instrumentation in
6037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      places.  Scan the whole bb even if dodgyness is found earlier,
6038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      so that the flatness assertion is applied to all stmts. */
6039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bogus = False;
6041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < sb_in->stmts_used; i++) {
6043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sb_in->stmts[i];
6045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(st);
6046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isFlatIRStmt(st));
6047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!bogus) {
6049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bogus = checkForBogusLiterals(st);
6050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0 && bogus) {
6051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("bogus: ");
6052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
6053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
6054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.bogusLiterals = bogus;
6060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy verbatim any IR preamble preceding the first IMark */
6062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(mce.sb == sb_out);
6064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(mce.sb != sb_in);
6065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = 0;
6067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (i < sb_in->stmts_used && sb_in->stmts[i]->tag != Ist_IMark) {
6068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sb_in->stmts[i];
6070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(st);
6071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isFlatIRStmt(st));
6072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'C', &mce, sb_in->stmts[i] );
6074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i++;
6075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Nasty problem.  IR optimisation of the pre-instrumented IR may
6078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cause the IR following the preamble to contain references to IR
6079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      temporaries defined in the preamble.  Because the preamble isn't
6080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      instrumented, these temporaries don't have any shadows.
6081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Nevertheless uses of them following the preamble will cause
6082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memcheck to generate references to their shadows.  End effect is
6083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to cause IR sanity check failures, due to references to
6084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      non-existent shadows.  This is only evident for the complex
6085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      preambles used for function wrapping on TOC-afflicted platforms
6086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      (ppc64-linux).
6087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The following loop therefore scans the preamble looking for
6089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignments to temporaries.  For each one found it creates an
6090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignment to the corresponding (V) shadow temp, marking it as
6091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'defined'.  This is the same resulting IR as if the main
6092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      instrumentation loop before had been applied to the statement
6093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'tmp = CONSTANT'.
6094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Similarly, if origin tracking is enabled, we must generate an
6096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignment for the corresponding origin (B) shadow, claiming
6097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      no-origin, as appropriate for a defined value.
6098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
6099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j < i; j++) {
6100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sb_in->stmts[j]->tag == Ist_WrTmp) {
6101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* findShadowTmpV checks its arg is an original tmp;
6102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            no need to assert that here. */
6103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp tmp_o = sb_in->stmts[j]->Ist.WrTmp.tmp;
6104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp tmp_v = findShadowTmpV(&mce, tmp_o);
6105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType ty_v  = typeOfIRTemp(sb_out->tyenv, tmp_v);
6106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( 'V', &mce, tmp_v, definedOfType( ty_v ) );
6107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (MC_(clo_mc_level) == 3) {
6108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp tmp_b = findShadowTmpB(&mce, tmp_o);
6109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(typeOfIRTemp(sb_out->tyenv, tmp_b) == Ity_I32);
6110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( 'B', &mce, tmp_b, mkU32(0)/* UNKNOWN ORIGIN */);
6111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) {
6113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("create shadow tmp(s) for preamble tmp [%d] ty ", j);
6114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRType( ty_v );
6115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
6116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Iterate over the remaining stmts to generate instrumentation. */
6121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sb_in->stmts_used > 0);
6123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(i >= 0);
6124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(i < sb_in->stmts_used);
6125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sb_in->stmts[i]->tag == Ist_IMark);
6126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (/* use current i*/; i < sb_in->stmts_used; i++) {
6128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sb_in->stmts[i];
6130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      first_stmt = sb_out->stmts_used;
6131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (verboze) {
6133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
6134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
6135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
6136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (MC_(clo_mc_level) == 3) {
6139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* See comments on case Ist_CAS below. */
6140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->tag != Ist_CAS)
6141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            schemeS( &mce, st );
6142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate instrumentation code for each stmt ... */
6145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
6147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_WrTmp:
6149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( 'V', &mce, findShadowTmpV(&mce, st->Ist.WrTmp.tmp),
6150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               expr2vbits( &mce, st->Ist.WrTmp.data) );
6151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put:
6154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_PUT( &mce,
6155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           st->Ist.Put.offset,
6156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           st->Ist.Put.data,
6157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           NULL /* shadow atom */, NULL /* guard */ );
6158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_PutI:
6161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do_shadow_PUTI( &mce, st->Ist.PutI.details);
6162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Store:
6165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_Store( &mce, st->Ist.Store.end,
6166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   st->Ist.Store.addr, 0/* addr bias */,
6167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   st->Ist.Store.data,
6168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   NULL /* shadow data */,
6169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   NULL/*guard*/ );
6170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_StoreG:
6173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            do_shadow_StoreG( &mce, st->Ist.StoreG.details );
6174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
6175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_LoadG:
6177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            do_shadow_LoadG( &mce, st->Ist.LoadG.details );
6178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
6179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Exit:
6181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            complainIfUndefined( &mce, st->Ist.Exit.guard, NULL );
6182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_IMark:
6185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_NoOp:
6188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_MBE:
6189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Dirty:
6192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_Dirty( &mce, st->Ist.Dirty.details );
6193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_AbiHint:
6196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_AbiHint( &mce, st->Ist.AbiHint.base,
6197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              st->Ist.AbiHint.len,
6198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              st->Ist.AbiHint.nia );
6199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS:
6202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_CAS( &mce, st->Ist.CAS.details );
6203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note, do_shadow_CAS copies the CAS itself to the output
6204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               block, because it needs to add instrumentation both
6205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               before and after it.  Hence skip the copy below.  Also
6206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               skip the origin-tracking stuff (call to schemeS) above,
6207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               since that's all tangled up with it too; do_shadow_CAS
6208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               does it all. */
6209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_LLSC:
6212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_LLSC( &mce,
6213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.LLSC.end,
6214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.LLSC.result,
6215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.LLSC.addr,
6216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.LLSC.storedata );
6217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
6218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
6220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
6221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
6222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
6223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(tool_panic)("memcheck: unhandled IRStmt");
6224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* switch (st->tag) */
6226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 && verboze) {
6228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = first_stmt; j < sb_out->stmts_used; j++) {
6229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("   ");
6230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(sb_out->stmts[j]);
6231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
6232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
6234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ... and finally copy the stmt itself to the output.  Except,
6237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         skip the copy of IRCASs; see comments on case Ist_CAS
6238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         above. */
6239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_CAS)
6240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt('C', &mce, st);
6241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now we need to complain if the jump target is undefined. */
6244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   first_stmt = sb_out->stmts_used;
6245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (verboze) {
6247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("sb_in->next = ");
6248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(sb_in->next);
6249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n\n");
6250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   complainIfUndefined( &mce, sb_in->next, NULL );
6253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0 && verboze) {
6255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = first_stmt; j < sb_out->stmts_used; j++) {
6256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("   ");
6257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(sb_out->stmts[j]);
6258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
6259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
6261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If this fails, there's been some serious snafu with tmp management,
6264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that should be investigated. */
6265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( VG_(sizeXA)( mce.tmpMap ) == mce.sb->tyenv->types_used );
6266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(deleteXA)( mce.tmpMap );
6267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(mce.sb == sb_out);
6269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sb_out;
6270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Post-tree-build final tidying                        ---*/
6274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This exploits the observation that Memcheck often produces
6277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   repeated conditional calls of the form
6278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Dirty G MC_(helperc_value_check0/1/4/8_fail)(UInt otag)
6280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with the same guard expression G guarding the same helper call.
6282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The second and subsequent calls are redundant.  This usually
6283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   results from instrumentation of guest code containing multiple
6284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   memory references at different constant offsets from the same base
6285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register.  After optimisation of the instrumentation, you get a
6286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   test for the definedness of the base register for each memory
6287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reference, which is kinda pointless.  MC_(final_tidy) therefore
6288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   looks for such repeated calls and removes all but the first. */
6289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A struct for recording which (helper, guard) pairs we have already
6291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   seen. */
6292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
6293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct { void* entry; IRExpr* guard; }
6294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Pair;
6295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True if e1 and e2 definitely denote the same value (used to
6297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   compare guards).  Return False if unknown; False is the safe
6298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   answer.  Since guest registers and guest memory do not have the
6299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SSA property we must return False if any Gets or Loads appear in
6300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the expression. */
6301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sameIRValue ( IRExpr* e1, IRExpr* e2 )
6303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e1->tag != e2->tag)
6305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e1->tag) {
6307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
6308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return eqIRConst( e1->Iex.Const.con, e2->Iex.Const.con );
6309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
6310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e1->Iex.Binop.op == e2->Iex.Binop.op
6311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && sameIRValue(e1->Iex.Binop.arg1, e2->Iex.Binop.arg1)
6312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && sameIRValue(e1->Iex.Binop.arg2, e2->Iex.Binop.arg2);
6313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
6314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e1->Iex.Unop.op == e2->Iex.Unop.op
6315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && sameIRValue(e1->Iex.Unop.arg, e2->Iex.Unop.arg);
6316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
6317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp;
6318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE:
6319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return sameIRValue( e1->Iex.ITE.cond, e2->Iex.ITE.cond )
6320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                && sameIRValue( e1->Iex.ITE.iftrue,  e2->Iex.ITE.iftrue )
6321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                && sameIRValue( e1->Iex.ITE.iffalse, e2->Iex.ITE.iffalse );
6322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
6323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
6324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
6325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* be lazy.  Could define equality for these, but they never
6326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            appear to be used. */
6327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
6329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
6330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
6331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* be conservative - these may not give the same value each
6332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            time */
6333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binder:
6335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* should never see this */
6336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthrough */
6337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("mc_translate.c: sameIRValue: unhandled: ");
6339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(e1);
6340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:sameIRValue");
6341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* See if 'pairs' already has an entry for (entry, guard).  Return
6346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   True if so.  If not, add an entry. */
6347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
6349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool check_or_add ( XArray* /*of Pair*/ pairs, IRExpr* guard, void* entry )
6350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Pair  p;
6352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Pair* pp;
6353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   i, n = VG_(sizeXA)( pairs );
6354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n; i++) {
6355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pp = VG_(indexXA)( pairs, i );
6356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (pp->entry == entry && sameIRValue(pp->guard, guard))
6357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
6358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p.guard = guard;
6360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p.entry = entry;
6361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(addToXA)( pairs, &p );
6362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
6363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool is_helperc_value_checkN_fail ( const HChar* name )
6366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
6368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0==VG_(strcmp)(name, "MC_(helperc_value_check0_fail_no_o)")
6369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check1_fail_no_o)")
6370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check4_fail_no_o)")
6371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check8_fail_no_o)")
6372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check0_fail_w_o)")
6373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check1_fail_w_o)")
6374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check4_fail_w_o)")
6375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check8_fail_w_o)");
6376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* MC_(final_tidy) ( IRSB* sb_in )
6379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
6381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*   st;
6382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty*  di;
6383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*   guard;
6384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCallee* cee;
6385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      alreadyPresent;
6386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XArray*   pairs = VG_(newXA)( VG_(malloc), "mc.ft.1",
6387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 VG_(free), sizeof(Pair) );
6388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scan forwards through the statements.  Each time a call to one
6389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of the relevant helpers is seen, check if we have made a
6390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      previous call to the same helper using the same guard
6391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expression, and if so, delete the call. */
6392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < sb_in->stmts_used; i++) {
6393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sb_in->stmts[i];
6394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(st);
6395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_Dirty)
6396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
6397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = st->Ist.Dirty.details;
6398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guard = di->guard;
6399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tl_assert(guard);
6400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) { ppIRExpr(guard); VG_(printf)("\n"); }
6401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cee = di->cee;
6402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!is_helperc_value_checkN_fail( cee->name ))
6403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
6404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       /* Ok, we have a call to helperc_value_check0/1/4/8_fail with
6405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          guard 'guard'.  Check if we have already seen a call to this
6406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          function with the same guard.  If so, delete it.  If not,
6407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          add it to the set of calls we do know about. */
6408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      alreadyPresent = check_or_add( pairs, guard, cee->addr );
6409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (alreadyPresent) {
6410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sb_in->stmts[i] = IRStmt_NoOp();
6411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("XX\n");
6412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(deleteXA)( pairs );
6415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sb_in;
6416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Origin tracking stuff                                ---*/
6421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Almost identical to findShadowTmpV. */
6424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp findShadowTmpB ( MCEnv* mce, IRTemp orig )
6425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt* ent;
6427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VG_(indexXA) range-checks 'orig', hence no need to check
6428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      here. */
6429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
6430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ent->kind == Orig);
6431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ent->shadowB == IRTemp_INVALID) {
6432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmpB
6433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = newTemp( mce, Ity_I32, BSh );
6434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* newTemp may cause mce->tmpMap to resize, hence previous results
6435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         from VG_(indexXA) are invalid. */
6436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
6437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->kind == Orig);
6438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->shadowB == IRTemp_INVALID);
6439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent->shadowB = tmpB;
6440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ent->shadowB;
6442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* gen_maxU32 ( MCEnv* mce, IRAtom* b1, IRAtom* b2 )
6445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew( 'B', mce, Ity_I32, binop(Iop_Max32U, b1, b2) );
6447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Make a guarded origin load, with no special handling in the
6451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   didn't-happen case.  A GUARD of NULL is assumed to mean "always
6452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   True".
6453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Generate IR to do a shadow origins load from BASEADDR+OFFSET and
6455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return the otag.  The loaded size is SZB.  If GUARD evaluates to
6456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   False at run time then the returned otag is zero.
6457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
6458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic IRAtom* gen_guarded_load_b ( MCEnv* mce, Int szB,
6459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    IRAtom* baseaddr,
6460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    Int offset, IRExpr* guard )
6461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*    hFun;
6463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* hName;
6464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp   bTmp;
6465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
6466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   aTy   = typeOfIRExpr( mce->sb->tyenv, baseaddr );
6467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp     opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
6468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  ea    = baseaddr;
6469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (offset != 0) {
6470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom* off = aTy == Ity_I32 ? mkU32( offset )
6471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   : mkU64( (Long)(Int)offset );
6472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ea = assignNew( 'B', mce, aTy, binop(opAdd, ea, off));
6473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bTmp = newTemp(mce, mce->hWordTy, BSh);
6475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (szB) {
6477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: hFun  = (void*)&MC_(helperc_b_load1);
6478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_load1)";
6479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
6480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: hFun  = (void*)&MC_(helperc_b_load2);
6481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_load2)";
6482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
6483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: hFun  = (void*)&MC_(helperc_b_load4);
6484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_load4)";
6485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
6486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: hFun  = (void*)&MC_(helperc_b_load8);
6487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_load8)";
6488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
6489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 16: hFun  = (void*)&MC_(helperc_b_load16);
6490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               hName = "MC_(helperc_b_load16)";
6491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 32: hFun  = (void*)&MC_(helperc_b_load32);
6493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               hName = "MC_(helperc_b_load32)";
6494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
6495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("mc_translate.c: gen_load_b: unhandled szB == %d\n", szB);
6497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
6498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_1_N(
6500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bTmp, 1/*regparms*/, hName, VG_(fnptr_to_fnentry)( hFun ),
6501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           mkIRExprVec_1( ea )
6502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
6503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (guard) {
6504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      di->guard = guard;
6505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Ideally the didn't-happen return value here would be
6506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         all-zeroes (unknown-origin), so it'd be harmless if it got
6507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         used inadvertantly.  We slum it out with the IR-mandated
6508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         default value (0b01 repeating, 0x55 etc) as that'll probably
6509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         trump all legitimate otags via Max32, and it's pretty
6510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         obviously bogus. */
6511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
6512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no need to mess with any annotations.  This call accesses
6513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      neither guest state nor guest memory. */
6514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'B', mce, IRStmt_Dirty(di) );
6515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mce->hWordTy == Ity_I64) {
6516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64-bit host */
6517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp bTmp32 = newTemp(mce, Ity_I32, BSh);
6518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'B', mce, bTmp32, unop(Iop_64to32, mkexpr(bTmp)) );
6519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mkexpr(bTmp32);
6520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
6521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32-bit host */
6522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mkexpr(bTmp);
6523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Generate IR to do a shadow origins load from BASEADDR+OFFSET.  The
6528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   loaded size is SZB.  The load is regarded as unconditional (always
6529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   happens).
6530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
6531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic IRAtom* gen_load_b ( MCEnv* mce, Int szB, IRAtom* baseaddr,
6532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            Int offset )
6533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
6534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return gen_guarded_load_b(mce, szB, baseaddr, offset, NULL/*guard*/);
6535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
6536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* The most general handler for guarded origin loads.  A GUARD of NULL
6539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   is assumed to mean "always True".
6540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Generate IR to do a shadow origin load from ADDR+BIAS and return
6542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   the B bits.  The loaded type is TY.  If GUARD evaluates to False at
6543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   run time then the returned B bits are simply BALT instead.
6544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
6545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
6546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRAtom* expr2ori_Load_guarded_General ( MCEnv* mce,
6547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        IRType ty,
6548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        IRAtom* addr, UInt bias,
6549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        IRAtom* guard, IRAtom* balt )
6550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
6551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* If the guard evaluates to True, this will hold the loaded
6552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      origin.  If the guard evaluates to False, this will be zero,
6553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      meaning "unknown origin", in which case we will have to replace
6554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      it using an ITE below. */
6555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* iftrue
6556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = assignNew('B', mce, Ity_I32,
6557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  gen_guarded_load_b(mce, sizeofIRType(ty),
6558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                     addr, bias, guard));
6559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* These are the bits we will return if the load doesn't take
6560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      place. */
6561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* iffalse
6562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = balt;
6563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Prepare the cond for the ITE.  Convert a NULL cond into
6564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      something that iropt knows how to fold out later. */
6565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* cond
6566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = guard == NULL  ? mkU1(1)  : guard;
6567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* And assemble the final result. */
6568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return assignNew('B', mce, Ity_I32, IRExpr_ITE(cond, iftrue, iffalse));
6569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
6570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Generate a shadow origins store.  guard :: Ity_I1 controls whether
6573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   the store really happens; NULL means it unconditionally does. */
6574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_store_b ( MCEnv* mce, Int szB,
6575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* baseaddr, Int offset, IRAtom* dataB,
6576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* guard )
6577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*    hFun;
6579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* hName;
6580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
6581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   aTy   = typeOfIRExpr( mce->sb->tyenv, baseaddr );
6582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp     opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
6583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  ea    = baseaddr;
6584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) {
6585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, guard));
6586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(typeOfIRExpr(mce->sb->tyenv, guard) == Ity_I1);
6587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (offset != 0) {
6589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom* off = aTy == Ity_I32 ? mkU32( offset )
6590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   : mkU64( (Long)(Int)offset );
6591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ea = assignNew(  'B', mce, aTy, binop(opAdd, ea, off));
6592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mce->hWordTy == Ity_I64)
6594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dataB = assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, dataB));
6595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (szB) {
6597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: hFun  = (void*)&MC_(helperc_b_store1);
6598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_store1)";
6599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
6600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: hFun  = (void*)&MC_(helperc_b_store2);
6601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_store2)";
6602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
6603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: hFun  = (void*)&MC_(helperc_b_store4);
6604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_store4)";
6605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
6606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: hFun  = (void*)&MC_(helperc_b_store8);
6607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_store8)";
6608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
6609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 16: hFun  = (void*)&MC_(helperc_b_store16);
6610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               hName = "MC_(helperc_b_store16)";
6611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 32: hFun  = (void*)&MC_(helperc_b_store32);
6613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               hName = "MC_(helperc_b_store32)";
6614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
6615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
6617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_0_N( 2/*regparms*/,
6619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           hName, VG_(fnptr_to_fnentry)( hFun ),
6620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           mkIRExprVec_2( ea, dataB )
6621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
6622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no need to mess with any annotations.  This call accesses
6623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      neither guest state nor guest memory. */
6624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) di->guard = guard;
6625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'B', mce, IRStmt_Dirty(di) );
6626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* narrowTo32 ( MCEnv* mce, IRAtom* e ) {
6629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType eTy = typeOfIRExpr(mce->sb->tyenv, e);
6630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (eTy == Ity_I64)
6631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew( 'B', mce, Ity_I32, unop(Iop_64to32, e) );
6632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (eTy == Ity_I32)
6633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return e;
6634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0);
6635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* zWidenFrom32 ( MCEnv* mce, IRType dstTy, IRAtom* e ) {
6638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType eTy = typeOfIRExpr(mce->sb->tyenv, e);
6639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(eTy == Ity_I32);
6640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (dstTy == Ity_I64)
6641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, e) );
6642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0);
6643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* schemeE ( MCEnv* mce, IRExpr* e )
6647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(MC_(clo_mc_level) == 3);
6649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
6651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI: {
6653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr_b;
6654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom      *t1, *t2, *t3, *t4;
6655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr      = e->Iex.GetI.descr;
6656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType equivIntTy
6657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = MC_(get_otrack_reg_array_equiv_int_type)(descr);
6658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If this array is unshadowable for whatever reason, use the
6659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            usual approximation. */
6660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (equivIntTy == Ity_INVALID)
6661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return mkU32(0);
6662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(sizeofIRType(equivIntTy) >= 4);
6663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(sizeofIRType(equivIntTy) == sizeofIRType(descr->elemTy));
6664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         descr_b = mkIRRegArray( descr->base + 2*mce->layout->total_sizeB,
6665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 equivIntTy, descr->nElems );
6666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Do a shadow indexed get of the same size, giving t1.  Take
6667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the bottom 32 bits of it, giving t2.  Compute into t3 the
6668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            origin for the index (almost certainly zero, but there's
6669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            no harm in being completely general here, since iropt will
6670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            remove any useless code), and fold it in, giving a final
6671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            value t4. */
6672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = assignNew( 'B', mce, equivIntTy,
6673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRExpr_GetI( descr_b, e->Iex.GetI.ix,
6674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                e->Iex.GetI.bias ));
6675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t2 = narrowTo32( mce, t1 );
6676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t3 = schemeE( mce, e->Iex.GetI.ix );
6677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t4 = gen_maxU32( mce, t2, t3 );
6678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return t4;
6679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall: {
6681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int i;
6682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom*  here;
6683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr** args = e->Iex.CCall.args;
6684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom*  curr = mkU32(0);
6685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; args[i]; i++) {
6686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(i < 32);
6687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(isOriginalAtom(mce, args[i]));
6688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Only take notice of this arg if the callee's
6689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mc-exclusion mask does not say it is to be excluded. */
6690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (e->Iex.CCall.cee->mcx_mask & (1<<i)) {
6691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* the arg is to be excluded from definedness checking.
6692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Do nothing. */
6693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (0) VG_(printf)("excluding %s(%d)\n",
6694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  e->Iex.CCall.cee->name, i);
6695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* calculate the arg's definedness, and pessimistically
6697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  merge it in. */
6698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               here = schemeE( mce, args[i] );
6699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               curr = gen_maxU32( mce, curr, here );
6700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return curr;
6703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load: {
6705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int dszB;
6706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dszB = sizeofIRType(e->Iex.Load.ty);
6707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* assert that the B value for the address is already
6708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            available (somewhere) */
6709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(isIRAtom(e->Iex.Load.addr));
6710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(mce->hWordTy == Ity_I32 || mce->hWordTy == Ity_I64);
6711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return gen_load_b( mce, dszB, e->Iex.Load.addr, 0 );
6712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iex_ITE: {
6714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRAtom* b1 = schemeE( mce, e->Iex.ITE.cond );
6715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRAtom* b3 = schemeE( mce, e->Iex.ITE.iftrue );
6716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRAtom* b2 = schemeE( mce, e->Iex.ITE.iffalse );
6717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return gen_maxU32( mce, b1, gen_maxU32( mce, b2, b3 ));
6718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop: {
6720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRAtom* b1 = schemeE( mce, e->Iex.Qop.details->arg1 );
6721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRAtom* b2 = schemeE( mce, e->Iex.Qop.details->arg2 );
6722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRAtom* b3 = schemeE( mce, e->Iex.Qop.details->arg3 );
6723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRAtom* b4 = schemeE( mce, e->Iex.Qop.details->arg4 );
6724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return gen_maxU32( mce, gen_maxU32( mce, b1, b2 ),
6725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 gen_maxU32( mce, b3, b4 ) );
6726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop: {
6728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRAtom* b1 = schemeE( mce, e->Iex.Triop.details->arg1 );
6729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRAtom* b2 = schemeE( mce, e->Iex.Triop.details->arg2 );
6730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRAtom* b3 = schemeE( mce, e->Iex.Triop.details->arg3 );
6731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return gen_maxU32( mce, b1, gen_maxU32( mce, b2, b3 ) );
6732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop: {
6734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
6735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CasCmpEQ8:  case Iop_CasCmpNE8:
6736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CasCmpEQ16: case Iop_CasCmpNE16:
6737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CasCmpEQ32: case Iop_CasCmpNE32:
6738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CasCmpEQ64: case Iop_CasCmpNE64:
6739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Just say these all produce a defined result,
6740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  regardless of their arguments.  See
6741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  COMMENT_ON_CasCmpEQ in this file. */
6742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return mkU32(0);
6743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: {
6744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRAtom* b1 = schemeE( mce, e->Iex.Binop.arg1 );
6745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRAtom* b2 = schemeE( mce, e->Iex.Binop.arg2 );
6746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return gen_maxU32( mce, b1, b2 );
6747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
6750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*NOTREACHED*/
6751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop: {
6753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b1 = schemeE( mce, e->Iex.Unop.arg );
6754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return b1;
6755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
6757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkU32(0);
6758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
6759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkexpr( findShadowTmpB( mce, e->Iex.RdTmp.tmp ));
6760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get: {
6761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int b_offset = MC_(get_otrack_shadow_offset)(
6762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           e->Iex.Get.offset,
6763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           sizeofIRType(e->Iex.Get.ty)
6764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        );
6765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(b_offset >= -1
6766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   && b_offset <= mce->layout->total_sizeB -4);
6767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b_offset >= 0) {
6768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* FIXME: this isn't an atom! */
6769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return IRExpr_Get( b_offset + 2*mce->layout->total_sizeB,
6770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Ity_I32 );
6771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkU32(0);
6773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("mc_translate.c: schemeE: unhandled: ");
6776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(e);
6777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:schemeE");
6778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_origins_Dirty ( MCEnv* mce, IRDirty* d )
6783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // This is a hacked version of do_shadow_Dirty
6785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int       i, k, n, toDo, gSz, gOff;
6786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom    *here, *curr;
6787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp    dst;
6788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First check the guard. */
6790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   curr = schemeE( mce, d->guard );
6791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now round up all inputs and maxU32 over them. */
6793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Inputs: unmasked args
6795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Note: arguments are evaluated REGARDLESS of the guard expression */
6796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; d->args[i]; i++) {
6797436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRAtom* arg = d->args[i];
6798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if ( (d->cee->mcx_mask & (1<<i))
6799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           || UNLIKELY(is_IRExpr_VECRET_or_BBPTR(arg)) ) {
6800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ignore this arg */
6801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
6802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         here = schemeE( mce, arg );
6803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = gen_maxU32( mce, curr, here );
6804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: guest state that we read. */
6808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < d->nFxState; i++) {
6809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->fxState[i].fx != Ifx_None);
6810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->fxState[i].fx == Ifx_Write)
6811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
6812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Enumerate the described state segments */
6814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (k = 0; k < 1 + d->fxState[i].nRepeats; k++) {
6815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gOff = d->fxState[i].offset + k * d->fxState[i].repeatLen;
6816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gSz  = d->fxState[i].size;
6817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Ignore any sections marked as 'always defined'. */
6819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (isAlwaysDefd(mce, gOff, gSz)) {
6820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0)
6821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
6822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        gOff, gSz);
6823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            continue;
6824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
6825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* This state element is read or modified.  So we need to
6827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            consider it.  If larger than 4 bytes, deal with it in
6828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            4-byte chunks. */
6829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         while (True) {
6830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int b_offset;
6831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            tl_assert(gSz >= 0);
6832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (gSz == 0) break;
6833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            n = gSz <= 4 ? gSz : 4;
6834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* update 'curr' with maxU32 of the state slice
6835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               gOff .. gOff+n-1 */
6836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            b_offset = MC_(get_otrack_shadow_offset)(gOff, 4);
6837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (b_offset != -1) {
6838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Observe the guard expression. If it is false use 0, i.e.
6839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  nothing is known about the origin */
6840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               IRAtom *cond, *iffalse, *iftrue;
6841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               cond = assignNew( 'B', mce, Ity_I1, d->guard);
6843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               iffalse = mkU32(0);
6844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               iftrue  = assignNew( 'B', mce, Ity_I32,
6845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    IRExpr_Get(b_offset
6846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                                 + 2*mce->layout->total_sizeB,
6847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               Ity_I32));
6848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               here = assignNew( 'B', mce, Ity_I32,
6849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                 IRExpr_ITE(cond, iftrue, iffalse));
6850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               curr = gen_maxU32( mce, curr, here );
6851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
6852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gSz -= n;
6853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gOff += n;
6854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: memory */
6859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx != Ifx_None) {
6861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Because we may do multiple shadow loads/stores from the same
6862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base address, it's best to do a single test of its
6863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         definedness right now.  Post-instrumentation optimisation
6864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         should remove all but this test. */
6865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->mAddr);
6866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      here = schemeE( mce, d->mAddr );
6867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      curr = gen_maxU32( mce, curr, here );
6868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with memory inputs (reads or modifies) */
6871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
6872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toDo   = d->mSize;
6873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 32-bit chunks.  We don't care about the endianness
6874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         since it's all going to be condensed down to a single bit,
6875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         but nevertheless choose an endianness which is hopefully
6876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         native to the platform. */
6877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 4) {
6878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         here = gen_guarded_load_b( mce, 4, d->mAddr, d->mSize - toDo,
6879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    d->guard );
6880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = gen_maxU32( mce, curr, here );
6881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 4;
6882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* handle possible 16-bit excess */
6884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 2) {
6885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         here = gen_guarded_load_b( mce, 2, d->mAddr, d->mSize - toDo,
6886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    d->guard );
6887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = gen_maxU32( mce, curr, here );
6888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 2;
6889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* chew off the remaining 8-bit chunk, if any */
6891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (toDo == 1) {
6892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         here = gen_guarded_load_b( mce, 1, d->mAddr, d->mSize - toDo,
6893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    d->guard );
6894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         curr = gen_maxU32( mce, curr, here );
6895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         toDo -= 1;
6896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
6897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      tl_assert(toDo == 0);
6898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Whew!  So curr is a 32-bit B-value which should give an origin
6901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of some use if any of the inputs to the helper are undefined.
6902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Now we need to re-distribute the results to all destinations. */
6903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: the destination temporary, if there is one. */
6905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->tmp != IRTemp_INVALID) {
6906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst   = findShadowTmpB(mce, d->tmp);
6907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'V', mce, dst, curr );
6908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: guest state that we write or modify. */
6911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < d->nFxState; i++) {
6912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->fxState[i].fx != Ifx_None);
6913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->fxState[i].fx == Ifx_Read)
6914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
6915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Enumerate the described state segments */
6917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (k = 0; k < 1 + d->fxState[i].nRepeats; k++) {
6918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gOff = d->fxState[i].offset + k * d->fxState[i].repeatLen;
6919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gSz  = d->fxState[i].size;
6920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Ignore any sections marked as 'always defined'. */
6922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (isAlwaysDefd(mce, gOff, gSz))
6923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            continue;
6924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* This state element is written or modified.  So we need to
6926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            consider it.  If larger than 4 bytes, deal with it in
6927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            4-byte chunks. */
6928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         while (True) {
6929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int b_offset;
6930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            tl_assert(gSz >= 0);
6931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (gSz == 0) break;
6932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            n = gSz <= 4 ? gSz : 4;
6933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Write 'curr' to the state slice gOff .. gOff+n-1 */
6934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            b_offset = MC_(get_otrack_shadow_offset)(gOff, 4);
6935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (b_offset != -1) {
6936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* If the guard expression evaluates to false we simply Put
6938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  the value that is already stored in the guest state slot */
6939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               IRAtom *cond, *iffalse;
6940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               cond    = assignNew('B', mce, Ity_I1,
6942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                   d->guard);
6943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               iffalse = assignNew('B', mce, Ity_I32,
6944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                   IRExpr_Get(b_offset +
6945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                              2*mce->layout->total_sizeB,
6946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                              Ity_I32));
6947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               curr = assignNew('V', mce, Ity_I32,
6948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                IRExpr_ITE(cond, curr, iffalse));
6949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               stmt( 'B', mce, IRStmt_Put(b_offset
6951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                          + 2*mce->layout->total_sizeB,
6952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          curr ));
6953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
6954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gSz -= n;
6955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            gOff += n;
6956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: memory that we write or modify.  Same comments about
6961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      endianness as above apply. */
6962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
6963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toDo   = d->mSize;
6964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 32-bit chunks */
6965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 4) {
6966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_store_b( mce, 4, d->mAddr, d->mSize - toDo, curr,
6967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      d->guard );
6968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 4;
6969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* handle possible 16-bit excess */
6971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 2) {
6972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         gen_store_b( mce, 2, d->mAddr, d->mSize - toDo, curr,
6973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      d->guard );
6974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 2;
6975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* chew off the remaining 8-bit chunk, if any */
6977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (toDo == 1) {
6978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         gen_store_b( mce, 1, d->mAddr, d->mSize - toDo, curr,
6979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      d->guard );
6980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         toDo -= 1;
6981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
6982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      tl_assert(toDo == 0);
6983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Generate IR for origin shadowing for a general guarded store. */
6988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void do_origins_Store_guarded ( MCEnv* mce,
6989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       IREndness stEnd,
6990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       IRExpr* stAddr,
6991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       IRExpr* stData,
6992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       IRExpr* guard )
6993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     dszB;
6995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* dataB;
6996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* assert that the B value for the address is already available
6997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (somewhere), since the call to schemeE will want to see it.
6998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XXXX how does this actually ensure that?? */
6999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(stAddr));
7000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(stData));
7001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dszB  = sizeofIRType( typeOfIRExpr(mce->sb->tyenv, stData ) );
7002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dataB = schemeE( mce, stData );
7003436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   gen_store_b( mce, dszB, stAddr, 0/*offset*/, dataB, guard );
7004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
7005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7007436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Generate IR for origin shadowing for a plain store. */
7008436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void do_origins_Store_plain ( MCEnv* mce,
7009436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                     IREndness stEnd,
7010436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                     IRExpr* stAddr,
7011436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                     IRExpr* stData )
7012436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
7013436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   do_origins_Store_guarded ( mce, stEnd, stAddr, stData,
7014436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                              NULL/*guard*/ );
7015436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
7016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7018436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* ---- Dealing with LoadG/StoreG (not entirely simple) ---- */
7019436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7020436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void do_origins_StoreG ( MCEnv* mce, IRStoreG* sg )
7021436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
7022436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   do_origins_Store_guarded( mce, sg->end, sg->addr,
7023436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             sg->data, sg->guard );
7024436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
7025436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7026436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void do_origins_LoadG ( MCEnv* mce, IRLoadG* lg )
7027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
7028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRType loadedTy = Ity_INVALID;
7029436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (lg->cvt) {
7030436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_Ident32: loadedTy = Ity_I32; break;
7031436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_16Uto32: loadedTy = Ity_I16; break;
7032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_16Sto32: loadedTy = Ity_I16; break;
7033436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_8Uto32:  loadedTy = Ity_I8;  break;
7034436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ILGop_8Sto32:  loadedTy = Ity_I8;  break;
7035436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default: VG_(tool_panic)("schemeS.IRLoadG");
7036436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
7037436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* ori_alt
7038436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = schemeE( mce,lg->alt );
7039436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRAtom* ori_final
7040436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = expr2ori_Load_guarded_General(mce, loadedTy,
7041436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                      lg->addr, 0/*addr bias*/,
7042436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                      lg->guard, ori_alt );
7043436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* And finally, bind the origin to the destination temporary. */
7044436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   assign( 'B', mce, findShadowTmpB(mce, lg->dst), ori_final );
7045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void schemeS ( MCEnv* mce, IRStmt* st )
7049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(MC_(clo_mc_level) == 3);
7051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
7053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
7055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The value-check instrumenter handles this - by arranging
7056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            to pass the address of the next instruction to
7057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            MC_(helperc_MAKE_STACK_UNINIT).  This is all that needs to
7058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            happen for origin tracking w.r.t. AbiHints.  So there is
7059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nothing to do here. */
7060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI: {
7063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRPutI *puti = st->Ist.PutI.details;
7064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr_b;
7065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom      *t1, *t2, *t3, *t4;
7066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRRegArray* descr = puti->descr;
7067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType equivIntTy
7068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = MC_(get_otrack_reg_array_equiv_int_type)(descr);
7069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If this array is unshadowable for whatever reason,
7070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            generate no code. */
7071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (equivIntTy == Ity_INVALID)
7072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(sizeofIRType(equivIntTy) >= 4);
7074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(sizeofIRType(equivIntTy) == sizeofIRType(descr->elemTy));
7075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         descr_b
7076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = mkIRRegArray( descr->base + 2*mce->layout->total_sizeB,
7077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            equivIntTy, descr->nElems );
7078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Compute a value to Put - the conjoinment of the origin for
7079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the data to be Put-ted (obviously) and of the index value
7080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (not so obviously). */
7081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t1 = schemeE( mce, puti->data );
7082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         t2 = schemeE( mce, puti->ix );
7083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t3 = gen_maxU32( mce, t1, t2 );
7084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t4 = zWidenFrom32( mce, equivIntTy, t3 );
7085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( 'B', mce, IRStmt_PutI( mkIRPutI(descr_b, puti->ix,
7086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               puti->bias, t4) ));
7087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
7091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_origins_Dirty( mce, st->Ist.Dirty.details );
7092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
7095436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         do_origins_Store_plain( mce, st->Ist.Store.end,
7096436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                      st->Ist.Store.addr,
7097436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                      st->Ist.Store.data );
7098436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
7099436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_StoreG:
7101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         do_origins_StoreG( mce, st->Ist.StoreG.details );
7102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
7103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ist_LoadG:
7105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         do_origins_LoadG( mce, st->Ist.LoadG.details );
7106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC: {
7109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* In short: treat a load-linked like a normal load followed
7110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            by an assignment of the loaded (shadow) data the result
7111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            temporary.  Treat a store-conditional like a normal store,
7112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            and mark the result temporary as defined. */
7113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata == NULL) {
7114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Load Linked */
7115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRType resTy
7116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = typeOfIRTemp(mce->sb->tyenv, st->Ist.LLSC.result);
7117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* vanillaLoad
7118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = IRExpr_Load(st->Ist.LLSC.end, resTy, st->Ist.LLSC.addr);
7119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(resTy == Ity_I64 || resTy == Ity_I32
7120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || resTy == Ity_I16 || resTy == Ity_I8);
7121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( 'B', mce, findShadowTmpB(mce, st->Ist.LLSC.result),
7122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              schemeE(mce, vanillaLoad));
7123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
7124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Store conditional */
7125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            do_origins_Store_plain( mce, st->Ist.LLSC.end,
7126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    st->Ist.LLSC.addr,
7127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    st->Ist.LLSC.storedata );
7128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* For the rationale behind this, see comments at the
7129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               place where the V-shadow for .result is constructed, in
7130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               do_shadow_LLSC.  In short, we regard .result as
7131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               always-defined. */
7132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( 'B', mce, findShadowTmpB(mce, st->Ist.LLSC.result),
7133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(0) );
7134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put: {
7139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int b_offset
7140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = MC_(get_otrack_shadow_offset)(
7141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 st->Ist.Put.offset,
7142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 sizeofIRType(typeOfIRExpr(mce->sb->tyenv, st->Ist.Put.data))
7143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
7144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b_offset >= 0) {
7145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* FIXME: this isn't an atom! */
7146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( 'B', mce, IRStmt_Put(b_offset + 2*mce->layout->total_sizeB,
7147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       schemeE( mce, st->Ist.Put.data )) );
7148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
7153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( 'B', mce, findShadowTmpB(mce, st->Ist.WrTmp.tmp),
7154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           schemeE(mce, st->Ist.WrTmp.data) );
7155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
7158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
7159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
7160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
7161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("mc_translate.c: schemeS: unhandled: ");
7165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
7166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:schemeS");
7167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
7172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                           mc_translate.c ---*/
7173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
7174