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
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2000-2011 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"
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_hashtable.h"     // For mc_include.h
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h"     // VG_(fnptr_to_fnentry)
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_xarray.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "mc_include.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* FIXMEs JRS 2011-June-16.
46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Check the interpretation for vector narrowing and widening ops,
48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   particularly the saturating ones.  I suspect they are either overly
49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pessimistic and/or wrong.
50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This file implements the Memcheck instrumentation, and in
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   particular contains the core of its undefined value detection
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   machinery.  For a comprehensive background of the terminology,
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   algorithms and rationale used herein, read:
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Using Valgrind to detect undefined value errors with
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     bit-precision
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Julian Seward and Nicholas Nethercote
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     2005 USENIX Annual Technical Conference (General Track),
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Anaheim, CA, USA, April 10-15, 2005.
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ----
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Here is as good a place as any to record exactly when V bits are and
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   should be checked, why, and what function is responsible.
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Memcheck complains when an undefined value is used:
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   1. In the condition of a conditional branch.  Because it could cause
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      incorrect control flow, and thus cause incorrect externally-visible
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      behaviour.  [mc_translate.c:complainIfUndefined]
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   2. As an argument to a system call, or as the value that specifies
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the system call number.  Because it could cause an incorrect
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      externally-visible side effect.  [mc_translate.c:mc_pre_reg_read]
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   3. As the address in a load or store.  Because it could cause an
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      incorrect value to be used later, which could cause externally-visible
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      behaviour (eg. via incorrect control flow or an incorrect system call
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argument)  [complainIfUndefined]
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   4. As the target address of a branch.  Because it could cause incorrect
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      control flow.  [complainIfUndefined]
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   5. As an argument to setenv, unsetenv, or putenv.  Because it could put
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an incorrect value into the external environment.
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      [mc_replace_strmem.c:VG_WRAP_FUNCTION_ZU(*, *env)]
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   6. As the index in a GETI or PUTI operation.  I'm not sure why... (njn).
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      [complainIfUndefined]
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   7. As an argument to the VALGRIND_CHECK_MEM_IS_DEFINED and
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_CHECK_VALUE_IS_DEFINED client requests.  Because the user
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      requested it.  [in memcheck.h]
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Memcheck also complains, but should not, when an undefined value is used:
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   8. As the shift value in certain SIMD shift operations (but not in the
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      standard integer shift operations).  This inconsistency is due to
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      historical reasons.)  [complainIfUndefined]
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Memcheck does not complain, but should, when an undefined value is used:
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   9. As an input to a client request.  Because the client request may
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      affect the visible behaviour -- see bug #144362 for an example
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      involving the malloc replacements in vg_replace_malloc.c and
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VALGRIND_NON_SIMD_CALL* requests, where an uninitialised argument
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      isn't identified.  That bug report also has some info on how to solve
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the problem.  [valgrind.h:VALGRIND_DO_CLIENT_REQUEST]
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In practice, 1 and 2 account for the vast majority of cases.
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Forward decls                                        ---*/
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct _MCEnv;
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRType  shadowTypeV ( IRType ty );
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp  findShadowTmpB ( struct _MCEnv* mce, IRTemp orig );
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr *i128_const_zero(void);
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Memcheck running state, and tmp management.          ---*/
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Carries info about a particular tmp.  The tmp's number is not
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   recorded, as this is implied by (equal to) its index in the tmpMap
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in MCEnv.  The tmp's type is also not recorded, as this is present
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in MCEnv.sb->tyenv.
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When .kind is Orig, .shadowV and .shadowB may give the identities
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of the temps currently holding the associated definedness (shadowV)
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and origin (shadowB) values, or these may be IRTemp_INVALID if code
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to compute such values has not yet been emitted.
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When .kind is VSh or BSh then the tmp is holds a V- or B- value,
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and so .shadowV and .shadowB must be IRTemp_INVALID, since it is
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   illogical for a shadow tmp itself to be shadowed.
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum { Orig=1, VSh=2, BSh=3 }
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempKind;
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TempKind kind;
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp   shadowV;
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp   shadowB;
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt;
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Carries around state during memcheck instrumentation. */
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct _MCEnv {
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* MODIFIED: the superblock being constructed.  IRStmts are
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         added. */
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRSB* sb;
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool  trace;
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         current kind and possibly shadow temps for each temp in the
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRSB being constructed.  Note that it does not contain the
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         type of each tmp.  If you want to know the type, look at the
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         relevant entry in sb->tyenv.  It follows that at all times
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         during the instrumentation process, the valid indices for
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmpMap and sb->tyenv are identical, being 0 .. N-1 where N is
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         total number of Orig, V- and B- temps allocated so far.
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         The reason for this strange split (types in one place, all
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         other info in another) is that we need the types to be
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         attached to sb so as to make it possible to do
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "typeOfIRExpr(mce->bb->tyenv, ...)" at various places in the
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         instrumentation process. */
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XArray* /* of TempMapEnt */ tmpMap;
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* MODIFIED: indicates whether "bogus" literals have so far been
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         found.  Starts off False, and may change to True. */
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool    bogusLiterals;
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* READONLY: the guest layout.  This indicates which parts of
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the guest state should be regarded as 'always defined'. */
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VexGuestLayout* layout;
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* READONLY: the host word type.  Needed for constructing
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arguments of type 'HWord' to be passed to helper functions.
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Ity_I32 or Ity_I64 only. */
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType hWordTy;
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MCEnv;
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* SHADOW TMP MANAGEMENT.  Shadow tmps are allocated lazily (on
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   demand), as they are encountered.  This is for two reasons.
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (1) (less important reason): Many original tmps are unused due to
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   initial IR optimisation, and we do not want to spaces in tables
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tracking them.
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Shadow IRTemps are therefore allocated on demand.  mce.tmpMap is a
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   table indexed [0 .. n_types-1], which gives the current shadow for
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   each original tmp, or INVALID_IRTEMP if none is so far assigned.
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   It is necessary to support making multiple assignments to a shadow
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- specifically, after testing a shadow for definedness, it needs
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to be made defined.  But IR's SSA property disallows this.
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (2) (more important reason): Therefore, when a shadow needs to get
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a new value, a new temporary is created, the value is assigned to
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that, and the tmpMap is updated to reflect the new binding.
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A corollary is that if the tmpMap maps a given tmp to
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp_INVALID and we are hoping to read that shadow tmp, it means
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   there's a read-before-write error in the original tmps.  The IR
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sanity checker should catch all such anomalies, however.
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create a new IRTemp of type 'ty' and kind 'kind', and add it to
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   both the table in mce->sb and to our auxiliary mapping.  Note that
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   newTemp may cause mce->tmpMap to resize, hence previous results
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   from VG_(indexXA)(mce->tmpMap) are invalidated. */
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp newTemp ( MCEnv* mce, IRType ty, TempKind kind )
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word       newIx;
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt ent;
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp     tmp = newIRTemp(mce->sb->tyenv, ty);
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent.kind    = kind;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent.shadowV = IRTemp_INVALID;
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent.shadowB = IRTemp_INVALID;
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   newIx = VG_(addToXA)( mce->tmpMap, &ent );
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(newIx == (Word)tmp);
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return tmp;
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Find the tmp currently shadowing the given original tmp.  If none
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so far exists, allocate one.  */
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp findShadowTmpV ( MCEnv* mce, IRTemp orig )
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt* ent;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VG_(indexXA) range-checks 'orig', hence no need to check
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      here. */
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ent->kind == Orig);
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ent->shadowV == IRTemp_INVALID) {
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmpV
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = newTemp( mce, shadowTypeV(mce->sb->tyenv->types[orig]), VSh );
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* newTemp may cause mce->tmpMap to resize, hence previous results
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         from VG_(indexXA) are invalid. */
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->kind == Orig);
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->shadowV == IRTemp_INVALID);
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent->shadowV = tmpV;
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ent->shadowV;
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Allocate a new shadow for the given original tmp.  This means any
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   previous shadow is abandoned.  This is needed because it is
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   necessary to give a new value to a shadow once it has been tested
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for undefinedness, but unfortunately IR's SSA property disallows
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this.  Instead we must abandon the old shadow, allocate a new one
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and use that instead.
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is the same as findShadowTmpV, except we don't bother to see
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if a shadow temp already existed -- we simply allocate a new one
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   regardless. */
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void newShadowTmpV ( MCEnv* mce, IRTemp orig )
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt* ent;
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VG_(indexXA) range-checks 'orig', hence no need to check
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      here. */
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ent->kind == Orig);
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (1) {
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmpV
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = newTemp( mce, shadowTypeV(mce->sb->tyenv->types[orig]), VSh );
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* newTemp may cause mce->tmpMap to resize, hence previous results
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         from VG_(indexXA) are invalid. */
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->kind == Orig);
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent->shadowV = tmpV;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- IRAtoms -- a subset of IRExprs                       ---*/
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   isIRAtom() in libvex_ir.h.  Because this instrumenter expects flat
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   input, most of this code deals in atoms.  Usefully, a value atom
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   always has a V-value which is also an atom: constants are shadowed
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by constants, and temps are shadowed by the corresponding shadow
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   temporary. */
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef  IRExpr  IRAtom;
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* (used for sanity checks only): is this an atom which looks
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   like it's from original code? */
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_Const)
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_RdTmp) {
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TempMapEnt* ent = VG_(indexXA)( mce->tmpMap, a1->Iex.RdTmp.tmp );
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ent->kind == Orig;
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* (used for sanity checks only): is this an atom which looks
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   like it's from shadow code? */
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_Const)
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_RdTmp) {
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TempMapEnt* ent = VG_(indexXA)( mce->tmpMap, a1->Iex.RdTmp.tmp );
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ent->kind == VSh || ent->kind == BSh;
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* (used for sanity checks only): check that both args are atoms and
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are identically-kinded. */
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_RdTmp && a2->tag == Iex_RdTmp)
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (a1->tag == Iex_Const && a2->tag == Iex_Const)
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Type management                                      ---*/
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Shadow state is always accessed using integer types.  This returns
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   an integer type with the same size (as per sizeofIRType) as the
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given type.  The only valid shadow types are Bit, I8, I16, I32,
354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   I64, I128, V128. */
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRType shadowTypeV ( IRType ty )
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I128: return ty;
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_F32:  return Ity_I32;
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_F64:  return Ity_I64;
367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ity_F128: return Ity_I128;
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128: return Ity_V128;
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: ppIRType(ty);
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(tool_panic)("memcheck:shadowTypeV");
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce a 'defined' value of the given shadow type.  Should only be
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   supplied shadow types (Bit/I8/I16/I32/UI64). */
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* definedOfType ( IRType ty ) {
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:   return IRExpr_Const(IRConst_U1(False));
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:   return IRExpr_Const(IRConst_U8(0));
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:  return IRExpr_Const(IRConst_U16(0));
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:  return IRExpr_Const(IRConst_U32(0));
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:  return IRExpr_Const(IRConst_U64(0));
383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ity_I128: return i128_const_zero();
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128: return IRExpr_Const(IRConst_V128(0x0000));
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:       VG_(tool_panic)("memcheck:definedOfType");
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Constructing IR fragments                            ---*/
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add stmt to a bb */
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void stmt ( HChar cat, MCEnv* mce, IRStmt* st ) {
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mce->trace) {
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  %c: ", cat);
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRStmt(st);
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addStmtToIRSB(mce->sb, st);
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* assign value to tmp */
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid assign ( HChar cat, MCEnv* mce, IRTemp tmp, IRExpr* expr ) {
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt(cat, mce, IRStmt_WrTmp(tmp,expr));
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* build various kinds of expressions */
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define triop(_op, _arg1, _arg2, _arg3) \
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRExpr_Triop((_op),(_arg1),(_arg2),(_arg3))
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define unop(_op, _arg)          IRExpr_Unop((_op),(_arg))
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkU8(_n)                 IRExpr_Const(IRConst_U8(_n))
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkU16(_n)                IRExpr_Const(IRConst_U16(_n))
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkU32(_n)                IRExpr_Const(IRConst_U32(_n))
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkU64(_n)                IRExpr_Const(IRConst_U64(_n))
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkV128(_n)               IRExpr_Const(IRConst_V128(_n))
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define mkexpr(_tmp)             IRExpr_RdTmp((_tmp))
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Bind the given expression to a new temporary, and return the
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   temporary.  This effectively converts an arbitrary expression into
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   an atom.
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'ty' is the type of 'e' and hence the type that the new temporary
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   needs to be.  But passing it in is redundant, since we can deduce
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the type merely by inspecting 'e'.  So at least use that fact to
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert that the two types agree. */
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* assignNew ( HChar cat, MCEnv* mce, IRType ty, IRExpr* e )
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempKind k;
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp   t;
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   tyE = typeOfIRExpr(mce->sb->tyenv, e);
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cat) {
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 'V': k = VSh;  break;
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 'B': k = BSh;  break;
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 'C': k = Orig; break;
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* happens when we are making up new "orig"
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expressions, for IRCAS handling */
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: tl_assert(0);
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t = newTemp(mce, ty, k);
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(cat, mce, t, e);
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkexpr(t);
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- Helper functions for 128-bit ops                     ---*/
452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr *i128_const_zero(void)
454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  return binop(Iop_64HLto128, IRExpr_Const(IRConst_U64(0)),
456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               IRExpr_Const(IRConst_U64(0)));
457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* There are no 128-bit loads and/or stores. So we do not need to worry
460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   about that in expr2vbits_Load */
461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Constructing definedness primitive ops               ---*/
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Defined-if-either-defined --------- */
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I8, binop(Iop_And8, a1, a2));
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I16, binop(Iop_And16, a1, a2));
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, binop(Iop_And32, a1, a2));
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifD64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, binop(Iop_And64, a1, a2));
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkDifDV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, binop(Iop_AndV128, a1, a2));
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Undefined-if-either-undefined --------- */
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I8, binop(Iop_Or8, a1, a2));
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I16, binop(Iop_Or16, a1, a2));
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, binop(Iop_Or32, a1, a2));
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, binop(Iop_Or64, a1, a2));
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRAtom* mkUifU128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRAtom *tmp1, *tmp2, *tmp3, *tmp4, *tmp5, *tmp6;
526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(isShadowAtom(mce,a1));
527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(isShadowAtom(mce,a2));
528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp1 = assignNew('V', mce, Ity_I64, unop(Iop_128to64, a1));
529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp2 = assignNew('V', mce, Ity_I64, unop(Iop_128HIto64, a1));
530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp3 = assignNew('V', mce, Ity_I64, unop(Iop_128to64, a2));
531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp4 = assignNew('V', mce, Ity_I64, unop(Iop_128HIto64, a2));
532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp5 = assignNew('V', mce, Ity_I64, binop(Iop_Or64, tmp1, tmp3));
533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tmp6 = assignNew('V', mce, Ity_I64, binop(Iop_Or64, tmp2, tmp4));
534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return assignNew('V', mce, Ity_I128, binop(Iop_64HLto128, tmp6, tmp5));
536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifUV128 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a2));
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, binop(Iop_OrV128, a1, a2));
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (vty) {
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:   return mkUifU8(mce, a1, a2);
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:  return mkUifU16(mce, a1, a2);
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:  return mkUifU32(mce, a1, a2);
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:  return mkUifU64(mce, a1, a2);
550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ity_I128: return mkUifU128(mce, a1, a2);
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128: return mkUifUV128(mce, a1, a2);
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:mkUifU");
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- The Left-family of operations. --------- */
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I8, unop(Iop_Left8, a1));
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I16, unop(Iop_Left16, a1));
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, unop(Iop_Left32, a1));
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkLeft64 ( MCEnv* mce, IRAtom* a1 ) {
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,a1));
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, unop(Iop_Left64, a1));
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- 'Improvement' functions for AND/OR. --------- */
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ImproveAND(data, vbits) = data OR vbits.  Defined (0) data 0s give
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   defined (0); all other -> undefined (1).
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I8, binop(Iop_Or8, data, vbits));
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I16, binop(Iop_Or16, data, vbits));
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, binop(Iop_Or32, data, vbits));
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveAND64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, binop(Iop_Or64, data, vbits));
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveANDV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, binop(Iop_OrV128, data, vbits));
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ImproveOR(data, vbits) = ~data OR vbits.  Defined (0) data 1s give
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   defined (0); all other -> undefined (1).
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveOR8 ( 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(
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_I8,
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Or8,
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I8, unop(Iop_Not8, data)),
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew(
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_I16,
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Or16,
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I16, unop(Iop_Not16, data)),
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveOR32 ( 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(
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_I32,
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Or32,
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I32, unop(Iop_Not32, data)),
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveOR64 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew(
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_I64,
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Or64,
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, unop(Iop_Not64, data)),
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkImproveORV128 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, data));
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vbits));
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(data, vbits));
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew(
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             'V', mce, Ity_V128,
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_OrV128,
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, unop(Iop_NotV128, data)),
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vbits) );
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Pessimising casts. --------- */
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* The function returns an expression of type DST_TY. If any of the VBITS
691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   is undefined (value == 1) the resulting expression has all bits set to
692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   1. Otherwise, all bits are 0. */
693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  src_ty;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* tmp1;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note, dst_ty is a shadow type, not an original type. */
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First of all, collapse vbits down to a single bit. */
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vbits));
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   src_ty = typeOfIRExpr(mce->sb->tyenv, vbits);
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fast-track some common cases */
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I32 && dst_ty == Ity_I32)
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew('V', mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I64 && dst_ty == Ity_I64)
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew('V', mce, Ity_I64, unop(Iop_CmpwNEZ64, vbits));
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (src_ty == Ity_I32 && dst_ty == Ity_I64) {
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom* tmp = assignNew('V', mce, Ity_I32, unop(Iop_CmpwNEZ32, vbits));
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew('V', mce, Ity_I64, binop(Iop_32HLto64, tmp, tmp));
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Else do it the slow way .. */
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp1   = NULL;
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (src_ty) {
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = vbits;
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ8, vbits));
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ16, vbits));
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ32, vbits));
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I1, unop(Iop_CmpNEZ64, vbits));
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I128: {
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Gah.  Chop it in half, OR the halves together, and compare
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that with zero. */
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* tmp2 = assignNew('V', mce, Ity_I64, unop(Iop_128HIto64, vbits));
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* tmp3 = assignNew('V', mce, Ity_I64, unop(Iop_128to64, vbits));
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* tmp4 = assignNew('V', mce, Ity_I64, binop(Iop_Or64, tmp2, tmp3));
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1         = assignNew('V', mce, Ity_I1,
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       unop(Iop_CmpNEZ64, tmp4));
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRType(src_ty);
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("mkPCastTo(1)");
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(tmp1);
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now widen up to the dst type. */
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (dst_ty) {
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return tmp1;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I8, unop(Iop_1Sto8, tmp1));
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, unop(Iop_1Sto16, tmp1));
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, unop(Iop_1Sto32, tmp1));
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, unop(Iop_1Sto64, tmp1));
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128:
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I64,  unop(Iop_1Sto64, tmp1));
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_V128, binop(Iop_64HLtoV128, tmp1, tmp1));
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return tmp1;
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I128:
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I64,  unop(Iop_1Sto64, tmp1));
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp1 = assignNew('V', mce, Ity_I128, binop(Iop_64HLto128, tmp1, tmp1));
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return tmp1;
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRType(dst_ty);
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("mkPCastTo(2)");
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Accurate interpretation of CmpEQ/CmpNE. --------- */
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Normally, we can do CmpEQ/CmpNE by doing UifU on the arguments, and
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PCasting to Ity_U1.  However, sometimes it is necessary to be more
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   accurate.  The insight is that the result is defined if two
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   corresponding bits can be found, one from each argument, so that
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   both bits are defined but are different -- that makes EQ say "No"
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and NE say "Yes".  Hence, we compute an improvement term and DifD
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it onto the "normal" (UifU) result.
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The result is:
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PCastTo<1> (
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      -- naive version
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PCastTo<sz>( UifU<sz>(vxx, vyy) )
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      `DifD<sz>`
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      -- improvement term
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PCastTo<sz>( PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) ) )
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   )
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   where
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vec contains 0 (defined) bits where the corresponding arg bits
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     are defined but different, and 1 bits otherwise.
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vec = Or<sz>( vxx,   // 0 iff bit defined
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   vyy,   // 0 iff bit defined
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Not<sz>(Xor<sz>( xx, yy )) // 0 iff bits different
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     If any bit of vec is 0, the result is defined and so the
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     improvement term should produce 0...0, else it should produce
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     1...1.
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Hence require for the improvement term:
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if vec == 1...1 then 1...1 else 0...0
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ->
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        PCast<sz>( CmpEQ<sz> ( vec, 1...1 ) )
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This was extensively re-analysed and checked on 6 July 05.
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* expensiveCmpEQorNE ( MCEnv*  mce,
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    IRType  ty,
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    IRAtom* vxx, IRAtom* vyy,
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    IRAtom* xx,  IRAtom* yy )
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *naive, *vec, *improvement_term;
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *improved, *final_cast, *top;
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opDIFD, opUIFU, opXOR, opNOT, opCMP, opOR;
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vxx));
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vyy));
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,xx));
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,yy));
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(vxx,xx));
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(vyy,yy));
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opOR   = Iop_Or32;
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opDIFD = Iop_And32;
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opUIFU = Iop_Or32;
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opNOT  = Iop_Not32;
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opXOR  = Iop_Xor32;
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCMP  = Iop_CmpEQ32;
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         top    = mkU32(0xFFFFFFFF);
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opOR   = Iop_Or64;
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opDIFD = Iop_And64;
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opUIFU = Iop_Or64;
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opNOT  = Iop_Not64;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opXOR  = Iop_Xor64;
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCMP  = Iop_CmpEQ64;
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         top    = mkU64(0xFFFFFFFFFFFFFFFFULL);
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("expensiveCmpEQorNE");
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   naive
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkPCastTo(mce,ty,
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assignNew('V', mce, ty, binop(opUIFU, vxx, vyy)));
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vec
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew(
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           'V', mce,ty,
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop( opOR,
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assignNew('V', mce,ty, binop(opOR, vxx, vyy)),
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assignNew(
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     'V', mce,ty,
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop( opNOT,
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           assignNew('V', mce,ty, binop(opXOR, xx, yy))))));
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   improvement_term
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkPCastTo( mce,ty,
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce,Ity_I1, binop(opCMP, vec, top)));
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   improved
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew( 'V', mce,ty, binop(opDIFD, naive, improvement_term) );
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   final_cast
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkPCastTo( mce, Ity_I1, improved );
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return final_cast;
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Semi-accurate interpretation of CmpORD. --------- */
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CmpORD32{S,U} does PowerPC-style 3-way comparisons:
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CmpORD32S(x,y) = 1<<3   if  x <s y
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     = 1<<2   if  x >s y
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     = 1<<1   if  x == y
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and similarly the unsigned variant.  The default interpretation is:
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CmpORD32{S,U}#(x,y,x#,y#) = PCast(x# `UifU` y#)
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  & (7<<1)
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The "& (7<<1)" reflects the fact that all result bits except 3,2,1
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are zero and therefore defined (viz, zero).
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Also deal with a special case better:
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CmpORD32S(x,0)
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Here, bit 3 (LT) of the result is a copy of the top bit of x and
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   will be defined even if the rest of x isn't.  In which case we do:
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CmpORD32S#(x,x#,0,{impliedly 0}#)
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = PCast(x#) & (3<<1)      -- standard interp for GT#,EQ#
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | (x# >>u 31) << 3      -- LT# = x#[31]
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Analogous handling for CmpORD64{S,U}.
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU32 ( IRAtom* e )
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toBool( e->tag == Iex_Const
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && e->Iex.Const.con->tag == Ico_U32
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && e->Iex.Const.con->Ico.U32 == 0 );
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU64 ( IRAtom* e )
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toBool( e->tag == Iex_Const
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && e->Iex.Const.con->tag == Ico_U64
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && e->Iex.Const.con->Ico.U64 == 0 );
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* doCmpORD ( MCEnv*  mce,
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IROp    cmp_op,
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* xxhash, IRAtom* yyhash,
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* xx,     IRAtom* yy )
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   m64    = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U;
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   syned  = cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD32S;
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opOR   = m64 ? Iop_Or64  : Iop_Or32;
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opAND  = m64 ? Iop_And64 : Iop_And32;
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opSHL  = m64 ? Iop_Shl64 : Iop_Shl32;
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opSHR  = m64 ? Iop_Shr64 : Iop_Shr32;
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = m64 ? Ity_I64   : Ity_I32;
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    width  = m64 ? 64        : 32;
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool (*isZero)(IRAtom*) = m64 ? isZeroU64 : isZeroU32;
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* threeLeft1 = NULL;
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* sevenLeft1 = NULL;
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,xxhash));
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,yyhash));
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,xx));
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,yy));
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(xxhash,xx));
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(yyhash,yy));
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cmp_op == Iop_CmpORD32S || cmp_op == Iop_CmpORD32U
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || cmp_op == Iop_CmpORD64S || cmp_op == Iop_CmpORD64U);
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIROp(cmp_op); VG_(printf)(" ");
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(xx); VG_(printf)(" "); ppIRExpr( yy ); VG_(printf)("\n");
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (syned && isZero(yy)) {
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fancy interpretation */
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* if yy is zero, then it must be fully defined (zero#). */
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isZero(yyhash));
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      threeLeft1 = m64 ? mkU64(3<<1) : mkU32(3<<1);
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            opOR,
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assignNew(
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               'V', mce,ty,
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  opAND,
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkPCastTo(mce,ty, xxhash),
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  threeLeft1
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )),
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assignNew(
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               'V', mce,ty,
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  opSHL,
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assignNew(
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     'V', mce,ty,
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(opSHR, xxhash, mkU8(width-1))),
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU8(3)
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ))
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 );
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* standard interpretation */
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sevenLeft1 = m64 ? mkU64(7<<1) : mkU32(7<<1);
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            opAND,
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkPCastTo( mce,ty,
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkUifU(mce,ty, xxhash,yyhash)),
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sevenLeft1
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Emit a test and complaint if something is undefined. ---*/
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* schemeE ( MCEnv* mce, IRExpr* e ); /* fwds */
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the annotations on a dirty helper to indicate that the stack
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pointer and instruction pointers might be read.  This is the
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   behaviour of all 'emit-a-complaint' style functions we might
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call. */
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di->nFxState = 2;
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di->fxState[0].fx     = Ifx_Read;
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di->fxState[0].offset = mce->layout->offset_SP;
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di->fxState[0].size   = mce->layout->sizeof_SP;
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di->fxState[1].fx     = Ifx_Read;
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di->fxState[1].offset = mce->layout->offset_IP;
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di->fxState[1].size   = mce->layout->sizeof_IP;
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Check the supplied **original** atom for undefinedness, and emit a
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complaint if so.  Once that happens, mark it as defined.  This is
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possible because the atom is either a tmp or literal.  If it's a
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp, it will be shadowed by a tmp, and so we can set the shadow to
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be defined.  In fact as mentioned above, we will have to allocate a
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new tmp to carry the new 'defined' shadow value, and update the
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   original->tmp mapping accordingly; we cannot simply assign a new
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value to an existing shadow tmp as this breaks SSAness -- resulting
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in the post-instrumentation sanity checker spluttering in disapproval.
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  vatom;
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   ty;
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      sz;
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  cond;
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  origin;
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*    fn;
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar*   nm;
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args;
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      nargs;
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Don't do V bit tests if we're not reporting undefined value errors.
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 1)
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Since the original expression is atomic, there's no duplicated
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      work generated by making multiple V-expressions for it.  So we
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      don't really care about the possibility that someone else may
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      also create a V-interpretion for it. */
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, atom));
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vatom = expr2vbits( mce, atom );
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatom));
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom, vatom));
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = typeOfIRExpr(mce->sb->tyenv, vatom);
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sz is only used for constructing the error message */
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cond = mkPCastTo( mce, Ity_I1, vatom );
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* cond will be 0 if all defined, and 1 if any not defined. */
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Get the origin info for the value we are about to check.  At
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      least, if we are doing origin tracking.  If not, use a dummy
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      zero origin. */
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 3) {
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      origin = schemeE( mce, atom );
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mce->hWordTy == Ity_I64) {
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         origin = assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, origin) );
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      origin = NULL;
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fn    = NULL;
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   nm    = NULL;
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   args  = NULL;
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   nargs = -1;
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sz) {
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check0_fail_w_o);
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check0_fail_w_o)";
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1(origin);
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check0_fail_no_o);
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check0_fail_no_o)";
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_0();
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 0;
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check1_fail_w_o);
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check1_fail_w_o)";
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1(origin);
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check1_fail_no_o);
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check1_fail_no_o)";
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_0();
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 0;
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check4_fail_w_o);
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check4_fail_w_o)";
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1(origin);
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check4_fail_no_o);
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check4_fail_no_o)";
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_0();
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 0;
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check8_fail_w_o);
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check8_fail_w_o)";
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1(origin);
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_check8_fail_no_o);
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_check8_fail_no_o)";
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_0();
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 0;
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 16:
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (origin) {
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_checkN_fail_w_o);
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_checkN_fail_w_o)";
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_2( mkIRExpr_HWord( sz ), origin);
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 2;
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn    = &MC_(helperc_value_checkN_fail_no_o);
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm    = "MC_(helperc_value_checkN_fail_no_o)";
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            args  = mkIRExprVec_1( mkIRExpr_HWord( sz ) );
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nargs = 1;
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("unexpected szB");
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(fn);
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(nm);
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(args);
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(nargs >= 0 && nargs <= 2);
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( (MC_(clo_mc_level) == 3 && origin != NULL)
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || (MC_(clo_mc_level) == 2 && origin == NULL) );
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_0_N( nargs/*regparms*/, nm,
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           VG_(fnptr_to_fnentry)( fn ), args );
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di->guard = cond;
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setHelperAnns( mce, di );
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'V', mce, IRStmt_Dirty(di));
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set the shadow tmp to be defined.  First, update the
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      orig->shadow tmp mapping to reflect the fact that this shadow is
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      getting a new value. */
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(vatom));
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sameKindedAtoms ... */
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vatom->tag == Iex_RdTmp) {
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(atom->tag == Iex_RdTmp);
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      newShadowTmpV(mce, atom->Iex.RdTmp.tmp);
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign('V', mce, findShadowTmpV(mce, atom->Iex.RdTmp.tmp),
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       definedOfType(ty));
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Shadowing PUTs/GETs, and indexed variants thereof    ---*/
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Examine the always-defined sections declared in layout to see if
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the (offset,size) section is within one.  Note, is is an error to
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   partially fall into such a region: (offset,size) should either be
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   completely in such a region or completely not-in such a region.
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int minoffD, maxoffD, i;
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int minoff = offset;
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int maxoff = minoff + size - 1;
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert((minoff & ~0xFFFF) == 0);
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert((maxoff & ~0xFFFF) == 0);
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      minoffD = mce->layout->alwaysDefd[i].offset;
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert((minoffD & ~0xFFFF) == 0);
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert((maxoffD & ~0xFFFF) == 0);
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (maxoff < minoffD || maxoffD < minoff)
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue; /* no overlap */
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (minoff >= minoffD && maxoff <= maxoffD)
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True; /* completely contained in an always-defd section */
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(tool_panic)("memcheck:isAlwaysDefd:partial overlap");
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False; /* could not find any containing section */
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate into bb suitable actions to shadow this Put.  If the state
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   slice is marked 'always defined', do nothing.  Otherwise, write the
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   supplied V bits to the shadow state.  We can pass in either an
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   original atom or a V-atom, but not both.  In the former case the
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   relevant V-bits are then generated from the original.
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_shadow_PUT ( MCEnv* mce,  Int offset,
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IRAtom* atom, IRAtom* vatom )
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty;
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Don't do shadow PUTs if we're not doing undefined value checking.
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Their absence lets Vex's optimiser remove all the shadow computation
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // that they depend on, which includes GETs of the shadow registers.
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 1)
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (atom) {
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(!vatom);
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, atom));
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vatom = expr2vbits( mce, atom );
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(vatom);
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, vatom));
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = typeOfIRExpr(mce->sb->tyenv, vatom);
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ty != Ity_I1);
1246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(ty != Ity_I128);
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* later: no ... */
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* emit code to emit a complaint if any of the vbits are 1. */
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* complainIfUndefined(mce, atom); */
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Do a plain shadow Put. */
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'V', mce, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an expression which contains the V bits corresponding to the
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given GETI (passed in in pieces).
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_shadow_PUTI ( MCEnv* mce,
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRRegArray* descr,
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRAtom* ix, Int bias, IRAtom* atom )
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom;
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty, tyS;
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     arrSize;;
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Don't do shadow PUTIs if we're not doing undefined value checking.
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Their absence lets Vex's optimiser remove all the shadow computation
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // that they depend on, which includes GETIs of the shadow registers.
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 1)
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom));
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vatom = expr2vbits( mce, atom );
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom, vatom));
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty   = descr->elemTy;
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tyS  = shadowTypeV(ty);
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arrSize = descr->nElems * sizeofIRType(ty);
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ty != Ity_I1);
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,ix));
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complainIfUndefined(mce,ix);
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isAlwaysDefd(mce, descr->base, arrSize)) {
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* later: no ... */
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* emit code to emit a complaint if any of the vbits are 1. */
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* complainIfUndefined(mce, atom); */
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Do a cloned version of the Put that refers to the shadow
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         area. */
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRRegArray* new_descr
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkIRRegArray( descr->base + mce->layout->total_sizeB,
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         tyS, descr->nElems);
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'V', mce, IRStmt_PutI( new_descr, ix, bias, vatom ));
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an expression which contains the V bits corresponding to the
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given GET (passed in in pieces).
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType tyS = shadowTypeV(ty);
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ty != Ity_I1);
1308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   tl_assert(ty != Ity_I128);
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Always defined, return all zeroes of the relevant type */
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return definedOfType(tyS);
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* return a cloned version of the Get that refers to the shadow
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         area. */
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FIXME: this isn't an atom! */
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an expression which contains the V bits corresponding to the
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given GETI (passed in in pieces).
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* shadow_GETI ( MCEnv* mce,
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRRegArray* descr, IRAtom* ix, Int bias )
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty   = descr->elemTy;
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType tyS  = shadowTypeV(ty);
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int arrSize = descr->nElems * sizeofIRType(ty);
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ty != Ity_I1);
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,ix));
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complainIfUndefined(mce,ix);
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isAlwaysDefd(mce, descr->base, arrSize)) {
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Always defined, return all zeroes of the relevant type */
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return definedOfType(tyS);
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* return a cloned version of the Get that refers to the shadow
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         area. */
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRRegArray* new_descr
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkIRRegArray( descr->base + mce->layout->total_sizeB,
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         tyS, descr->nElems);
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_GetI( new_descr, ix, bias );
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Generating approximations for unknown operations,    ---*/
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- using lazy-propagate semantics                       ---*/
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Lazy propagation of undefinedness from two values, resulting in the
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   specified shadow type.
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t1 = typeOfIRExpr(mce->sb->tyenv, va1);
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t2 = typeOfIRExpr(mce->sb->tyenv, va2);
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va1));
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va2));
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The general case is inefficient because PCast is an expensive
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      operation.  Here are some special cases which use PCast only
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      once rather than twice. */
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I64 x I64 -> I64 */
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I64) {
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy2: I64 x I64 -> I64\n");
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, va1, va2);
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, at);
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I64 x I64 -> I32 */
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I64 && t2 == Ity_I64 && finalVty == Ity_I32) {
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy2: I64 x I64 -> I32\n");
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, va1, va2);
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I32, at);
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("mkLazy2 ");
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t1);
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("_");
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t2);
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("_");
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(finalVty);
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* General case: force everything via 32-bit intermediaries. */
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I32, va1);
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, finalVty, at);
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 3-arg version of the above. */
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* mkLazy3 ( MCEnv* mce, IRType finalVty,
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRAtom* va1, IRAtom* va2, IRAtom* va3 )
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t1 = typeOfIRExpr(mce->sb->tyenv, va1);
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t2 = typeOfIRExpr(mce->sb->tyenv, va2);
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t3 = typeOfIRExpr(mce->sb->tyenv, va3);
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va1));
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va2));
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va3));
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The general case is inefficient because PCast is an expensive
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      operation.  Here are some special cases which use PCast only
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      twice rather than three times. */
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I32 x I64 x I64 -> I64 */
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Standard FP idiom: rm x FParg1 x FParg2 -> FPresult */
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && finalVty == Ity_I64) {
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy3: I32 x I64 x I64 -> I64\n");
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Widen 1st arg to I64.  Since 1st arg is typically a rounding
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mode indication which is fully defined, this should get
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         folded out later. */
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, va1);
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now fold in 2nd and 3rd args. */
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va2);
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va3);
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* and PCast once again. */
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, at);
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I32 x I64 x I64 -> I32 */
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && finalVty == Ity_I32) {
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy3: I32 x I64 x I64 -> I32\n");
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, va1);
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va2);
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va3);
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I32, at);
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I32 x I32 x I32 -> I32 */
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32-bit FP idiom, as (eg) happens on ARM */
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I32 && t2 == Ity_I32 && t3 == Ity_I32
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && finalVty == Ity_I32) {
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy3: I32 x I32 x I32 -> I32\n");
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = va1;
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I32, at, va2);
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I32, at, va3);
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I32, at);
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* I32 x I128 x I128 -> I128 */
1461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Standard FP idiom: rm x FParg1 x FParg2 -> FPresult */
1462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (t1 == Ity_I32 && t2 == Ity_I128 && t3 == Ity_I128
1463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && finalVty == Ity_I128) {
1464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0) VG_(printf)("mkLazy3: I32 x I128 x I128 -> I128\n");
1465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Widen 1st arg to I128.  Since 1st arg is typically a rounding
1466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mode indication which is fully defined, this should get
1467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         folded out later. */
1468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkPCastTo(mce, Ity_I128, va1);
1469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Now fold in 2nd and 3rd args. */
1470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I128, at, va2);
1471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I128, at, va3);
1472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* and PCast once again. */
1473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkPCastTo(mce, Ity_I128, at);
1474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return at;
1475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (1) {
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("mkLazy3: ");
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t1);
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t2);
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t3);
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" -> ");
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(finalVty);
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0);
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* General case: force everything via 32-bit intermediaries. */
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I32, va1);
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va3));
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, finalVty, at);
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 4-arg version of the above. */
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* mkLazy4 ( MCEnv* mce, IRType finalVty,
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRAtom* va1, IRAtom* va2, IRAtom* va3, IRAtom* va4 )
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t1 = typeOfIRExpr(mce->sb->tyenv, va1);
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t2 = typeOfIRExpr(mce->sb->tyenv, va2);
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t3 = typeOfIRExpr(mce->sb->tyenv, va3);
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType t4 = typeOfIRExpr(mce->sb->tyenv, va4);
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va1));
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va2));
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va3));
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,va4));
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      twice rather than three times. */
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I32 x I64 x I64 x I64 -> I64 */
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Standard FP idiom: rm x FParg1 x FParg2 x FParg3 -> FPresult */
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (t1 == Ity_I32 && t2 == Ity_I64 && t3 == Ity_I64 && t4 == Ity_I64
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && finalVty == Ity_I64) {
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(printf)("mkLazy4: I32 x I64 x I64 x I64 -> I64\n");
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Widen 1st arg to I64.  Since 1st arg is typically a rounding
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mode indication which is fully defined, this should get
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         folded out later. */
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, va1);
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now fold in 2nd, 3rd, 4th args. */
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va2);
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va3);
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkUifU(mce, Ity_I64, at, va4);
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* and PCast once again. */
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at = mkPCastTo(mce, Ity_I64, at);
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return at;
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* I32 x I32 x I32 x I32 -> I32 */
1537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Standard FP idiom: rm x FParg1 x FParg2 x FParg3 -> FPresult */
1538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (t1 == Ity_I32 && t2 == Ity_I32 && t3 == Ity_I32 && t4 == Ity_I32
1539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && finalVty == Ity_I32) {
1540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (0) VG_(printf)("mkLazy4: I32 x I32 x I32 x I32 -> I32\n");
1541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = va1;
1542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Now fold in 2nd, 3rd, 4th args. */
1543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I32, at, va2);
1544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I32, at, va3);
1545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkUifU(mce, Ity_I32, at, va4);
1546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      at = mkPCastTo(mce, Ity_I32, at);
1547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return at;
1548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (1) {
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("mkLazy4: ");
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t1);
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t2);
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t3);
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" x ");
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(t4);
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" -> ");
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRType(finalVty);
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0);
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do the lazy propagation game from a null-terminated vector of
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   atoms.  This is presumably the arguments to a helper call, so the
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCallee info is also supplied in order that we can know which
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arguments should be ignored (via the .mcx_mask field).
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* mkLazyN ( MCEnv* mce,
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i;
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* here;
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* curr;
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  mergeTy;
1581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool    mergeTy64 = True;
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Decide on the type of the merge intermediary.  If all relevant
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      args are I64, then it's I64.  In all other circumstances, use
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      I32. */
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; exprvec[i]; i++) {
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(i < 32);
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, exprvec[i]));
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cee->mcx_mask & (1<<i))
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (typeOfIRExpr(mce->sb->tyenv, exprvec[i]) != Ity_I64)
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mergeTy64 = False;
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mergeTy = mergeTy64  ? Ity_I64  : Ity_I32;
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   curr    = definedOfType(mergeTy);
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; exprvec[i]; i++) {
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(i < 32);
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, exprvec[i]));
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Only take notice of this arg if the callee's mc-exclusion
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask does not say it is to be excluded. */
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cee->mcx_mask & (1<<i)) {
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* the arg is to be excluded from definedness checking.  Do
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nothing. */
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* calculate the arg's definedness, and pessimistically merge
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            it in. */
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = mkPCastTo( mce, mergeTy, expr2vbits(mce, exprvec[i]) );
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = mergeTy64
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   ? mkUifU64(mce, here, curr)
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   : mkUifU32(mce, here, curr);
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkPCastTo(mce, finalVtype, curr );
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Generating expensive sequences for exact carry-chain ---*/
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- propagation in add/sub and related operations.       ---*/
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expensiveAddSub ( MCEnv*  mce,
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Bool    add,
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRType  ty,
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* qaa, IRAtom* qbb,
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* aa,  IRAtom* bb )
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *a_min, *b_min, *a_max, *b_max;
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opAND, opOR, opXOR, opNOT, opADD, opSUB;
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,qaa));
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,qbb));
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,aa));
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,bb));
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(qaa,aa));
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(qbb,bb));
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ty) {
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opAND = Iop_And32;
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opOR  = Iop_Or32;
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opXOR = Iop_Xor32;
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opNOT = Iop_Not32;
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opADD = Iop_Add32;
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opSUB = Iop_Sub32;
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opAND = Iop_And64;
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opOR  = Iop_Or64;
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opXOR = Iop_Xor64;
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opNOT = Iop_Not64;
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opADD = Iop_Add64;
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opSUB = Iop_Sub64;
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("expensiveAddSub");
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // a_min = aa & ~qaa
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a_min = assignNew('V', mce,ty,
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(opAND, aa,
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  assignNew('V', mce,ty, unop(opNOT, qaa))));
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // b_min = bb & ~qbb
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   b_min = assignNew('V', mce,ty,
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(opAND, bb,
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  assignNew('V', mce,ty, unop(opNOT, qbb))));
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // a_max = aa | qaa
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a_max = assignNew('V', mce,ty, binop(opOR, aa, qaa));
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // b_max = bb | qbb
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   b_max = assignNew('V', mce,ty, binop(opOR, bb, qbb));
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (add) {
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignNew('V', mce,ty,
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop( opOR,
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                assignNew('V', mce,ty, binop(opOR, qaa, qbb)),
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                assignNew('V', mce,ty,
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( opXOR,
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          assignNew('V', mce,ty, binop(opADD, a_min, b_min)),
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          assignNew('V', mce,ty, binop(opADD, a_max, b_max))
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                )
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // result = (qaa | qbb) | ((a_min - b_max) ^ (a_max + b_min))
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignNew('V', mce,ty,
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop( opOR,
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                assignNew('V', mce,ty, binop(opOR, qaa, qbb)),
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                assignNew('V', mce,ty,
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( opXOR,
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          assignNew('V', mce,ty, binop(opSUB, a_min, b_max)),
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          assignNew('V', mce,ty, binop(opSUB, a_max, b_min))
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   )
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                )
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Scalar shifts.                                       ---*/
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce an interpretation for (aa << bb) (or >>s, >>u).  The basic
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   idea is to shift the definedness bits by the original shift amount.
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This introduces 0s ("defined") in new positions for left shifts and
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned right shifts, and copies the top definedness bit for
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   signed right shifts.  So, conveniently, applying the original shift
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   operator to the definedness bits for the left arg is exactly the
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   right thing to do:
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (qaa << bb)
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   However if the shift amount is undefined then the whole result
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is undefined.  Hence need:
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (qaa << bb) `UifU` PCast(qbb)
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If the shift amount bb is a literal than qbb will say 'all defined'
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and the UifU and PCast will get folded out by post-instrumentation
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   optimisation.
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* scalarShift ( MCEnv*  mce,
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRType  ty,
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IROp    original_op,
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* qaa, IRAtom* qbb,
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* aa,  IRAtom* bb )
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,qaa));
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,qbb));
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,aa));
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,bb));
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(qaa,aa));
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(qbb,bb));
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignNew(
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         'V', mce, ty,
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkUifU( mce, ty,
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 assignNew('V', mce, ty, binop(original_op, qaa, bb)),
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkPCastTo(mce, ty, qbb)
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for dealing with vector primops.             ---*/
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vector pessimisation -- pessimise within each lane individually. */
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast8x16 ( MCEnv* mce, IRAtom* at )
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ8x16, at));
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast16x8 ( MCEnv* mce, IRAtom* at )
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ16x8, at));
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast32x4 ( MCEnv* mce, IRAtom* at )
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ32x4, at));
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast64x2 ( MCEnv* mce, IRAtom* at )
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ64x2, at));
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast32x2 ( MCEnv* mce, IRAtom* at )
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, unop(Iop_CmpNEZ32x2, at));
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast16x4 ( MCEnv* mce, IRAtom* at )
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, unop(Iop_CmpNEZ16x4, at));
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast8x8 ( MCEnv* mce, IRAtom* at )
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I64, unop(Iop_CmpNEZ8x8, at));
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast16x2 ( MCEnv* mce, IRAtom* at )
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, unop(Iop_CmpNEZ16x2, at));
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* mkPCast8x4 ( MCEnv* mce, IRAtom* at )
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew('V', mce, Ity_I32, unop(Iop_CmpNEZ8x4, at));
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Here's a simple scheme capable of handling ops derived from SSE1
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code and while only generating ops that can be efficiently
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   implemented in SSE1. */
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* All-lanes versions are straightforward:
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   binary32Fx4(x,y)   ==> PCast32x4(UifUV128(x#,y#))
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unary32Fx4(x,y)    ==> PCast32x4(x#)
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Lowest-lane-only versions are more complex:
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   binary32F0x4(x,y)  ==> SetV128lo32(
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             x#,
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             PCast32(V128to32(UifUV128(x#,y#)))
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          )
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is perhaps not so obvious.  In particular, it's faster to
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do a V128-bit UifU and then take the bottom 32 bits than the more
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   obvious scheme of taking the bottom 32 bits of each operand
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and doing a 32-bit UifU.  Basically since UifU is fast and
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   chopping lanes off vector values is slow.
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Finally:
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unary32F0x4(x)     ==> SetV128lo32(
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             x#,
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             PCast32(V128to32(x#))
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          )
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Where:
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PCast32(v#)   = 1Sto32(CmpNE32(v#,0))
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PCast32x4(v#) = CmpNEZ32x4(v#)
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32Fx4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatomX, vatomY);
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, mkPCast32x4(mce, at));
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary32Fx4 ( MCEnv* mce, IRAtom* vatomX )
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, mkPCast32x4(mce, vatomX));
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32F0x4 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatomX, vatomY);
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I32, unop(Iop_V128to32, at));
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I32, at);
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary32F0x4 ( MCEnv* mce, IRAtom* vatomX )
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I32, unop(Iop_V128to32, vatomX));
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I32, at);
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo32, vatomX, at));
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- ... and ... 64Fx2 versions of the same ... --- */
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary64Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatomX, vatomY);
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, mkPCast64x2(mce, at));
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary64Fx2 ( MCEnv* mce, IRAtom* vatomX )
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, mkPCast64x2(mce, vatomX));
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary64F0x2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatomX, vatomY);
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, at));
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I64, at);
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary64F0x2 ( MCEnv* mce, IRAtom* vatomX )
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, vatomX));
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I64, at);
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_V128, binop(Iop_SetV128lo64, vatomX, at));
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- --- ... and ... 32Fx2 versions of the same --- --- */
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32Fx2 ( MCEnv* mce, IRAtom* vatomX, IRAtom* vatomY )
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomY));
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatomX, vatomY);
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I64, mkPCast32x2(mce, at));
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* unary32Fx2 ( MCEnv* mce, IRAtom* vatomX )
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vatomX));
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = assignNew('V', mce, Ity_I64, mkPCast32x2(mce, vatomX));
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- --- Vector saturated narrowing --- --- */
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* We used to do something very clever here, but on closer inspection
1961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   (2011-Jun-15), and in particular bug #279698, it turns out to be
1962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   wrong.  Part of the problem came from the fact that for a long
1963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   time, the IR primops to do with saturated narrowing were
1964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   underspecified and managed to confuse multiple cases which needed
1965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to be separate: the op names had a signedness qualifier, but in
1966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fact the source and destination signednesses needed to be specified
1967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   independently, so the op names really need two independent
1968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   signedness specifiers.
1969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   As of 2011-Jun-15 (ish) the underspecification was sorted out
1971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   properly.  The incorrect instrumentation remained, though.  That
1972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   has now (2011-Oct-22) been fixed.
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   What we now do is simple:
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Let the original narrowing op be QNarrowBinXtoYxZ, where Z is a
1977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   number of lanes, X is the source lane width and signedness, and Y
1978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   is the destination lane width and signedness.  In all cases the
1979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   destination lane width is half the source lane width, so the names
1980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   have a bit of redundancy, but are at least easy to read.
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   For example, Iop_QNarrowBin32Sto16Ux8 narrows 8 lanes of signed 32s
1983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to unsigned 16s.
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Let Vanilla(OP) be a function that takes OP, one of these
1986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   saturating narrowing ops, and produces the same "shaped" narrowing
1987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   op which is not saturating, but merely dumps the most significant
1988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   bits.  "same shape" means that the lane numbers and widths are the
1989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   same as with OP.
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   For example, Vanilla(Iop_QNarrowBin32Sto16Ux8)
1992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  = Iop_NarrowBin32to16x8,
1993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   that is, narrow 8 lanes of 32 bits to 8 lanes of 16 bits, by
1994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   dumping the top half of each lane.
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   So, with that in place, the scheme is simple, and it is simple to
1997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   pessimise each lane individually and then apply Vanilla(OP) so as
1998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   to get the result in the right "shape".  If the original OP is
1999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   QNarrowBinXtoYxZ then we produce
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Vanilla(OP)( PCast-X-to-X-x-Z(vatom1), PCast-X-to-X-x-Z(vatom2) )
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   or for the case when OP is unary (Iop_QNarrowUn*)
2004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Vanilla(OP)( PCast-X-to-X-x-Z(vatom) )
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIROp vanillaNarrowingOpOfShape ( IROp qnarrowOp )
2009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (qnarrowOp) {
2011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Binary: (128, 128) -> 128 */
2012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux16:
2013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16:
2014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Uto8Ux16:
2015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowBin16to8x16;
2016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Ux8:
2017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8:
2018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Uto16Ux8:
2019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowBin32to16x8;
2020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Binary: (64, 64) -> 64 */
2021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx4:
2022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowBin32to16x4;
2023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux8:
2024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx8:
2025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowBin16to8x8;
2026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Unary: 128 -> 64 */
2027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Uto32Ux2:
2028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Sx2:
2029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Ux2:
2030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowUn64to32x2;
2031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Uto16Ux4:
2032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Sx4:
2033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Ux4:
2034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowUn32to16x4;
2035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Uto8Ux8:
2036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Sx8:
2037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Ux8:
2038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return Iop_NarrowUn16to8x8;
2039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
2040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ppIROp(qnarrowOp);
2041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(tool_panic)("vanillaNarrowOpOfShape");
2042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic
2046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRAtom* vectorNarrowBinV128 ( MCEnv* mce, IROp narrow_op,
2047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              IRAtom* vatom1, IRAtom* vatom2)
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *at1, *at2, *at3;
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*pcast)( MCEnv*, IRAtom* );
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (narrow_op) {
2052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8: pcast = mkPCast32x4; break;
2053b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Uto16Ux8: pcast = mkPCast32x4; break;
2054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Ux8: pcast = mkPCast32x4; break;
2055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16: pcast = mkPCast16x8; break;
2056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Uto8Ux16: pcast = mkPCast16x8; break;
2057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux16: pcast = mkPCast16x8; break;
2058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: VG_(tool_panic)("vectorNarrowBinV128");
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IROp vanilla_narrow = vanillaNarrowingOpOfShape(narrow_op);
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at1 = assignNew('V', mce, Ity_V128, pcast(mce, vatom1));
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at2 = assignNew('V', mce, Ity_V128, pcast(mce, vatom2));
2065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   at3 = assignNew('V', mce, Ity_V128, binop(vanilla_narrow, at1, at2));
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at3;
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRAtom* vectorNarrowBin64 ( MCEnv* mce, IROp narrow_op,
2071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            IRAtom* vatom1, IRAtom* vatom2)
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *at1, *at2, *at3;
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*pcast)( MCEnv*, IRAtom* );
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (narrow_op) {
2076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx4: pcast = mkPCast32x2; break;
2077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx8:  pcast = mkPCast16x4; break;
2078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux8:  pcast = mkPCast16x4; break;
2079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: VG_(tool_panic)("vectorNarrowBin64");
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IROp vanilla_narrow = vanillaNarrowingOpOfShape(narrow_op);
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at1 = assignNew('V', mce, Ity_I64, pcast(mce, vatom1));
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at2 = assignNew('V', mce, Ity_I64, pcast(mce, vatom2));
2086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   at3 = assignNew('V', mce, Ity_I64, binop(vanilla_narrow, at1, at2));
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at3;
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRAtom* vectorNarrowUnV128 ( MCEnv* mce, IROp narrow_op,
2092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             IRAtom* vatom1)
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *at1, *at2;
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*pcast)( MCEnv*, IRAtom* );
20969bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root   tl_assert(isShadowAtom(mce,vatom1));
2097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* For vanilla narrowing (non-saturating), we can just apply
2098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      the op directly to the V bits. */
2099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (narrow_op) {
2100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn16to8x8:
2101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn32to16x4:
2102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn64to32x2:
2103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         at1 = assignNew('V', mce, Ity_I64, unop(narrow_op, vatom1));
2104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return at1;
2105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
2106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break; /* Do Plan B */
2107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Plan B: for ops that involve a saturation operation on the args,
2109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      we must PCast before the vanilla narrow. */
2110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (narrow_op) {
2111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Sx8:  pcast = mkPCast16x8; break;
2112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Ux8:  pcast = mkPCast16x8; break;
2113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Uto8Ux8:  pcast = mkPCast16x8; break;
2114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Sx4: pcast = mkPCast32x4; break;
2115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Ux4: pcast = mkPCast32x4; break;
2116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Uto16Ux4: pcast = mkPCast32x4; break;
2117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Sx2: pcast = mkPCast64x2; break;
2118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Ux2: pcast = mkPCast64x2; break;
2119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Uto32Ux2: pcast = mkPCast64x2; break;
2120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: VG_(tool_panic)("vectorNarrowUnV128");
2121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IROp vanilla_narrow = vanillaNarrowingOpOfShape(narrow_op);
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at1 = assignNew('V', mce, Ity_V128, pcast(mce, vatom1));
2124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   at2 = assignNew('V', mce, Ity_I64, unop(vanilla_narrow, at1));
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at2;
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovIRAtom* vectorWidenI64 ( MCEnv* mce, IROp longen_op,
2130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         IRAtom* vatom1)
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *at1, *at2;
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*pcast)( MCEnv*, IRAtom* );
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (longen_op) {
2135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen8Uto16x8:  pcast = mkPCast16x8; break;
2136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen8Sto16x8:  pcast = mkPCast16x8; break;
2137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen16Uto32x4: pcast = mkPCast32x4; break;
2138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen16Sto32x4: pcast = mkPCast32x4; break;
2139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen32Uto64x2: pcast = mkPCast64x2; break;
2140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen32Sto64x2: pcast = mkPCast64x2; break;
2141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: VG_(tool_panic)("vectorWidenI64");
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at1 = assignNew('V', mce, Ity_V128, unop(longen_op, vatom1));
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at2 = assignNew('V', mce, Ity_V128, pcast(mce, at1));
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at2;
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- --- Vector integer arithmetic --- --- */
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Simple ... UifU the args and per-lane pessimise the results. */
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- V128-bit versions --- */
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary8Ix16 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatom1, vatom2);
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast8x16(mce, at);
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary16Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatom1, vatom2);
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast16x8(mce, at);
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatom1, vatom2);
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast32x4(mce, at);
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary64Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifUV128(mce, vatom1, vatom2);
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast64x2(mce, at);
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- 64-bit versions --- */
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary8Ix8 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatom1, vatom2);
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast8x8(mce, at);
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary16Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatom1, vatom2);
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast16x4(mce, at);
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary32Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatom1, vatom2);
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast32x2(mce, at);
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary64Ix1 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU64(mce, vatom1, vatom2);
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCastTo(mce, Ity_I64, at);
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- 32-bit versions --- */
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary8Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU32(mce, vatom1, vatom2);
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast8x4(mce, at);
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* binary16Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* at;
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkUifU32(mce, vatom1, vatom2);
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at = mkPCast16x2(mce, at);
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return at;
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Generate shadow values from all kinds of IRExprs.    ---*/
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expr2vbits_Qop ( MCEnv* mce,
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IROp op,
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRAtom* atom1, IRAtom* atom2,
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRAtom* atom3, IRAtom* atom4 )
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom1 = expr2vbits( mce, atom1 );
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom2 = expr2vbits( mce, atom2 );
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom3 = expr2vbits( mce, atom3 );
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom4 = expr2vbits( mce, atom4 );
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom1));
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom2));
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom3));
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom4));
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom3));
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom4));
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom1,vatom1));
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom2,vatom2));
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom3,vatom3));
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom4,vatom4));
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MAddF64:
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MAddF64r32:
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MSubF64:
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MSubF64r32:
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x F64 x F64 x F64 -> F64 */
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy4(mce, Ity_I64, vatom1, vatom2, vatom3, vatom4);
2285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_MAddF32:
2287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_MSubF32:
2288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* I32(rm) x F32 x F32 x F32 -> F32 */
2289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy4(mce, Ity_I32, vatom1, vatom2, vatom3, vatom4);
2290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIROp(op);
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:expr2vbits_Qop");
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expr2vbits_Triop ( MCEnv* mce,
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IROp op,
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRAtom* atom1, IRAtom* atom2, IRAtom* atom3 )
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom1 = expr2vbits( mce, atom1 );
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom2 = expr2vbits( mce, atom2 );
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom3 = expr2vbits( mce, atom3 );
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom1));
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom2));
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom3));
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom3));
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom1,vatom1));
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom2,vatom2));
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom3,vatom3));
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
2317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_AddF128:
2318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_SubF128:
2319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_MulF128:
2320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivF128:
2321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* I32(rm) x F128 x F128 -> F128 */
2322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy3(mce, Ity_I128, vatom1, vatom2, vatom3);
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AddF64:
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AddF64r32:
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SubF64:
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SubF64r32:
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulF64:
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulF64r32:
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivF64:
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivF64r32:
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ScaleF64:
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Yl2xF64:
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Yl2xp1F64:
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AtanF64:
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PRemF64:
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PRem1F64:
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x F64 x F64 -> F64 */
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy3(mce, Ity_I64, vatom1, vatom2, vatom3);
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PRemC3210F64:
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PRem1C3210F64:
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x F64 x F64 -> I32 */
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy3(mce, Ity_I32, vatom1, vatom2, vatom3);
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AddF32:
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SubF32:
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulF32:
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivF32:
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x F32 x F32 -> I32 */
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy3(mce, Ity_I32, vatom1, vatom2, vatom3);
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ExtractV128:
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom3);
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, triop(op, vatom1, vatom2, atom3));
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Extract64:
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom3);
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, triop(op, vatom1, vatom2, atom3));
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetElem8x8:
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetElem16x4:
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetElem32x2:
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, triop(op, vatom1, atom2, vatom3));
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIROp(op);
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:expr2vbits_Triop");
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expr2vbits_Binop ( MCEnv* mce,
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IROp op,
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRAtom* atom1, IRAtom* atom2 )
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  and_or_ty;
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*uifu)    (MCEnv*, IRAtom*, IRAtom*);
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*difd)    (MCEnv*, IRAtom*, IRAtom*);
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom1 = expr2vbits( mce, atom1 );
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom2 = expr2vbits( mce, atom2 );
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom1));
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom2));
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom1));
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom2));
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom1,vatom1));
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sameKindedAtoms(atom2,vatom2));
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32-bit SIMD */
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x2:
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HAdd16Ux2:
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HAdd16Sx2:
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x2:
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HSub16Ux2:
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HSub16Sx2:
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx2:
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx2:
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary16Ix2(mce, vatom1, vatom2);
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x4:
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HAdd8Ux4:
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HAdd8Sx4:
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x4:
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HSub8Ux4:
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_HSub8Sx4:
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux4:
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux4:
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx4:
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx4:
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary8Ix4(mce, vatom1, vatom2);
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64-bit SIMD */
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN8x8:
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x4:
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x2:
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN8x8:
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x4:
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x2:
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x4:
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x2:
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN8x8:
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Same scheme as with all other shifts. */
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2));
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx4:
2428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx8:
2429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux8:
2430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorNarrowBin64(mce, op, vatom1, vatom2);
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Ux8:
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Sx8:
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Ux8:
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Sx8:
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Ux8:
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx8:
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux8:
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x8:
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Sx8:
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Ux8:
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x8:
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx8:
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux8:
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal8x8:
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl8x8:
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x8:
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul8x8:
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PolynomialMul8x8:
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary8Ix8(mce, vatom1, vatom2);
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Sx4:
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Ux4:
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Sx4:
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Ux4:
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Ux4:
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Ux4:
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx4:
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x4:
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul16x4:
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Sx4:
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Ux4:
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Sx4:
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Ux4:
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16x4:
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx4:
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Ux4:
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal16x4:
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl16x4:
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x4:
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulHi16Sx4:
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QRDMulHi16Sx4:
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary16Ix4(mce, vatom1, vatom2);
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32x2:
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32x2:
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Sx2:
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Ux2:
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Sx2:
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Ux2:
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Sx2:
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Ux2:
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32x2:
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32x2:
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Ux2:
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Sx2:
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Ux2:
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Sx2:
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal32x2:
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl32x2:
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulHi32Sx2:
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QRDMulHi32Sx2:
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32Ix2(mce, vatom1, vatom2);
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub64Ux1:
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub64Sx1:
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd64Ux1:
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd64Sx1:
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal64x1:
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl64x1:
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal64x1:
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary64Ix1(mce, vatom1, vatom2);
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN8Sx8:
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN8x8:
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN8x8:
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x8(mce, vatom1);
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN16Sx4:
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN16x4:
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN16x4:
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x4(mce, vatom1);
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN32Sx2:
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN32x2:
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN32x2:
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce, vatom1);
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN64Sx1:
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN64x1:
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN64x1:
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce, vatom1);
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax32Sx2:
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax32Ux2:
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin32Sx2:
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin32Ux2:
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax32Fx2:
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin32Fx2:
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(Iop_PwMax32Ux2, mkPCast32x2(mce, vatom1),
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast32x2(mce, vatom2)));
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax16Sx4:
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax16Ux4:
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin16Sx4:
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin16Ux4:
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(Iop_PwMax16Ux4, mkPCast16x4(mce, vatom1),
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast16x4(mce, vatom2)));
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax8Sx8:
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMax8Ux8:
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin8Sx8:
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwMin8Ux8:
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(Iop_PwMax8Ux8, mkPCast8x8(mce, vatom1),
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast8x8(mce, vatom2)));
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd32x2:
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd32Fx2:
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce,
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_I64, binop(Iop_PwAdd32x2, mkPCast32x2(mce, vatom1),
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast32x2(mce, vatom2))));
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd16x4:
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x4(mce,
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_I64, binop(op, mkPCast16x4(mce, vatom1),
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast16x4(mce, vatom2))));
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd8x8:
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x8(mce,
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_I64, binop(op, mkPCast8x8(mce, vatom1),
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast8x8(mce, vatom2))));
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl8x8:
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr8x8:
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar8x8:
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal8x8:
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(mce,
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2)),
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast8x8(mce,vatom2)
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl16x4:
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr16x4:
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar16x4:
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal16x4:
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(mce,
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2)),
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast16x4(mce,vatom2)
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl32x2:
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr32x2:
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar32x2:
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal32x2:
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(mce,
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2)),
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast32x2(mce,vatom2)
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64-bit data-steering */
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO32x2:
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO16x4:
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO8x8:
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI32x2:
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI16x4:
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI8x8:
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes8x8:
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes8x8:
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes16x4:
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes16x4:
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes8x8:
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes8x8:
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes16x4:
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes16x4:
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(op, vatom1, vatom2));
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem8x8:
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I8, binop(op, vatom1, atom2));
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem16x4:
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, binop(op, vatom1, atom2));
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem32x2:
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, binop(op, vatom1, atom2));
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Perm8x8: rearrange values in left arg using steering values
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        from right arg.  So rearrange the vbits in the same way but
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pessimise wrt steering values. */
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Perm8x8:
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2)),
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast8x8(mce, vatom2)
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V128-bit SIMD */
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN8x16:
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x8:
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x4:
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN64x2:
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN8x16:
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x8:
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x4:
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN64x2:
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN8x16:
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x8:
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x4:
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN64x2:
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Same scheme as with all other shifts.  Note: 22 Oct 05:
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            this is wrong now, scalar shifts are done properly lazily.
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Vector shifts should be fixed too. */
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2));
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V x V shifts/rotates are done using the standard lazy scheme. */
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl8x16:
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr8x16:
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar8x16:
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal8x16:
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol8x16:
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce,
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast8x16(mce,vatom2)
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl16x8:
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr16x8:
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar16x8:
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal16x8:
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol16x8:
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce,
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast16x8(mce,vatom2)
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl32x4:
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr32x4:
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar32x4:
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal32x4:
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol32x4:
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce,
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast32x4(mce,vatom2)
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl64x2:
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr64x2:
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar64x2:
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sal64x2:
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce,
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast64x2(mce,vatom2)
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32ToFixed32Ux4_RZ:
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32ToFixed32Sx4_RZ:
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Fixed32UToF32x4_RN:
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Fixed32SToF32x4_RN:
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce, vatom1);
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32ToFixed32Ux2_RZ:
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32ToFixed32Sx2_RZ:
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Fixed32UToF32x2_RN:
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Fixed32SToF32x2_RN:
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce, vatom1);
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux16:
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx16:
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x16:
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Ux16:
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Sx16:
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Ux16:
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Sx16:
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Sx16:
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Ux16:
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x16:
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Ux16:
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Sx16:
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux16:
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx16:
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal8x16:
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl8x16:
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x16:
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul8x16:
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PolynomialMul8x16:
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary8Ix16(mce, vatom1, vatom2);
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Ux8:
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx8:
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x8:
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul16x8:
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Sx8:
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Ux8:
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Sx8:
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Ux8:
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Sx8:
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Ux8:
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Sx8:
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Ux8:
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16x8:
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Ux8:
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Sx8:
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Ux8:
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx8:
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal16x8:
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl16x8:
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x8:
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulHi16Sx8:
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QRDMulHi16Sx8:
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary16Ix8(mce, vatom1, vatom2);
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32x4:
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Sx4:
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Ux4:
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32x4:
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Sx4:
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Ux4:
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Sx4:
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Ux4:
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal32x4:
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl32x4:
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg32Ux4:
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg32Sx4:
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32x4:
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Ux4:
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Sx4:
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Ux4:
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Sx4:
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32x4:
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulHi32Sx4:
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QRDMulHi32Sx4:
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32Ix4(mce, vatom1, vatom2);
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64x2:
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64x2:
2774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpEQ64x2:
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT64Sx2:
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSal64x2:
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShl64x2:
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd64Ux2:
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd64Sx2:
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub64Ux2:
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub64Sx2:
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary64Ix2(mce, vatom1, vatom2);
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8:
2785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Uto16Ux8:
2786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Ux8:
2787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16:
2788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Uto8Ux16:
2789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux16:
2790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorNarrowBinV128(mce, op, vatom1, vatom2);
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64Fx2:
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul64Fx2:
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min64Fx2:
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max64Fx2:
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div64Fx2:
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64Fx2:
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64Fx2:
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64Fx2:
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN64Fx2:
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64Fx2:
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary64Fx2(mce, vatom1, vatom2);
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64F0x2:
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul64F0x2:
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min64F0x2:
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max64F0x2:
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div64F0x2:
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64F0x2:
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64F0x2:
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64F0x2:
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN64F0x2:
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64F0x2:
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary64F0x2(mce, vatom1, vatom2);
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32Fx4:
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32Fx4:
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Fx4:
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Fx4:
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div32Fx4:
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32Fx4:
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32Fx4:
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32Fx4:
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN32Fx4:
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Fx4:
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGE32Fx4:
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32Fx4:
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recps32Fx4:
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rsqrts32Fx4:
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32Fx4(mce, vatom1, vatom2);
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32Fx2:
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32Fx2:
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Fx2:
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Fx2:
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32Fx2:
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Fx2:
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGE32Fx2:
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32Fx2:
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recps32Fx2:
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rsqrts32Fx2:
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32Fx2(mce, vatom1, vatom2);
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32F0x4:
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32F0x4:
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32F0x4:
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32F0x4:
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div32F0x4:
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32F0x4:
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32F0x4:
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32F0x4:
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN32F0x4:
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32F0x4:
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binary32F0x4(mce, vatom1, vatom2);
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN8Sx16:
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN8x16:
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN8x16:
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x16(mce, vatom1);
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN16Sx8:
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN16x8:
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN16x8:
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x8(mce, vatom1);
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN32Sx4:
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN32x4:
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN32x4:
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce, vatom1);
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN64Sx2:
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QShlN64x2:
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSalN64x2:
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce, vatom1);
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull32Sx2:
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull32Ux2:
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulLong32Sx2:
2883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorWidenI64(mce, Iop_Widen32Sto64x2,
2884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    mkUifU64(mce, vatom1, vatom2));
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull16Sx4:
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull16Ux4:
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QDMulLong16Sx4:
2889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorWidenI64(mce, Iop_Widen16Sto32x4,
2890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    mkUifU64(mce, vatom1, vatom2));
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull8Sx8:
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mull8Ux8:
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PolynomialMull8x8:
2895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorWidenI64(mce, Iop_Widen8Sto16x8,
2896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    mkUifU64(mce, vatom1, vatom2));
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd32x4:
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce,
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, binop(op, mkPCast32x4(mce, vatom1),
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast32x4(mce, vatom2))));
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd16x8:
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x8(mce,
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, binop(op, mkPCast16x8(mce, vatom1),
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast16x8(mce, vatom2))));
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAdd8x16:
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x16(mce,
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, binop(op, mkPCast8x16(mce, vatom1),
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkPCast8x16(mce, vatom2))));
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V128-bit data-steering */
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetV128lo32:
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetV128lo64:
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLtoV128:
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO64x2:
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO32x4:
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO16x8:
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO8x16:
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI64x2:
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI32x4:
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI16x8:
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI8x16:
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes8x16:
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes16x8:
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatOddLanes32x4:
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes8x16:
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes16x8:
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CatEvenLanes32x4:
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes8x16:
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes16x8:
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveOddLanes32x4:
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes8x16:
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes16x8:
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveEvenLanes32x4:
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, binop(op, vatom1, vatom2));
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem8x16:
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I8, binop(op, vatom1, atom2));
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem16x8:
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, binop(op, vatom1, atom2));
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem32x4:
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, binop(op, vatom1, atom2));
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_GetElem64x2:
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(op, vatom1, atom2));
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Perm8x16: rearrange values in left arg using steering values
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        from right arg.  So rearrange the vbits in the same way but
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        pessimise wrt steering values. */
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Perm8x16:
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2)),
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkPCast8x16(mce, vatom2)
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* These two take the lower half of each 16-bit lane, sign/zero
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        extend it to 32, and multiply together, producing a 32x4
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        result (and implicitly ignoring half the operand bits).  So
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        treat it as a bunch of independent 16x8 operations, but then
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        do 32-bit shifts left-right to copy the lower half results
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (which are all 0s or all 1s due to PCasting in binary16Ix8)
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        into the upper half of each result lane. */
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven16Ux8:
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven16Sx8: {
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* at;
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = binary16Ix8(mce,vatom1,vatom2);
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = assignNew('V', mce, Ity_V128, binop(Iop_ShlN32x4, at, mkU8(16)));
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = assignNew('V', mce, Ity_V128, binop(Iop_SarN32x4, at, mkU8(16)));
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 return at;
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Same deal as Iop_MullEven16{S,U}x8 */
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven8Ux16:
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven8Sx16: {
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* at;
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = binary8Ix16(mce,vatom1,vatom2);
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = assignNew('V', mce, Ity_V128, binop(Iop_ShlN16x8, at, mkU8(8)));
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at = assignNew('V', mce, Ity_V128, binop(Iop_SarN16x8, at, mkU8(8)));
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 return at;
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* narrow 2xV128 into 1xV128, hi half from left arg, in a 2 x
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         32x4 -> 16x8 laneage, discarding the upper half of each lane.
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Simply apply same op to the V bits, since this really no more
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         than a data steering operation. */
2992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin32to16x8:
2993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin16to8x16:
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128,
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(op, vatom1, vatom2));
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrV128:
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlV128:
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Same scheme as with all other shifts.  Note: 10 Nov 05:
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            this is wrong now, scalar shifts are done properly lazily.
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Vector shifts should be fixed too. */
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         complainIfUndefined(mce, atom2);
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, binop(op, vatom1, atom2));
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* I128-bit data-steering */
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLto128:
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I128, binop(op, vatom1, vatom2));
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Scalar floating point */
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F32toI64S:
3012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* I32(rm) x F32 -> I64 */
3013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64StoF32:
3016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* I32(rm) x I64 -> F32 */
3017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toInt:
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF32:
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toI64S:
3022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F64toI64U:
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I64StoF64:
3024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64UtoF64:
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SinF64:
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CosF64:
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_TanF64:
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_2xm1F64:
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SqrtF64:
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x I64/F64 -> I64/F64 */
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32toInt:
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SqrtF32:
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I32(rm) x I32/F32 -> I32/F32 */
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_SqrtF128:
3039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* I32(rm) x F128 -> F128 */
3040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I128, vatom1, vatom2);
3041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I32StoF32:
3043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F32toI32S:
3044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* First arg is I32 (rounding mode), second is F32/I32 (data). */
3045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128toI32S: /* IRRoundingMode(I32) x F128 -> signed I32  */
3048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128toF32:  /* IRRoundingMode(I32) x F128 -> F32         */
3049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128toI64S: /* IRRoundingMode(I32) x F128 -> signed I64  */
3052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128toF64:  /* IRRoundingMode(I32) x F128 -> F64         */
3053b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F64HLtoF128:
3056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return assignNew('V', mce, Ity_I128, binop(Iop_64HLto128, vatom1, vatom2));
3057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toI32U:
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toI32S:
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toF32:
3061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64UtoF32:
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* First arg is I32 (rounding mode), second is F64 (data). */
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F64toI16S:
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* First arg is I32 (rounding mode), second is F64 (data). */
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I16, vatom1, vatom2);
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpF32:
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpF64:
3071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpF128:
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* non-FP after here */
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivModU64to32:
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivModS64to32:
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivModU128to64:
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivModS128to64:
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I128, vatom1, vatom2);
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16HLto32:
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, binop(op, vatom1, vatom2));
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32HLto64:
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(op, vatom1, vatom2));
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivModS64to64:
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS64:
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU64: {
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vLo64 = mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vHi64 = mkPCastTo(mce, Ity_I64, vLo64);
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I128, binop(Iop_64HLto128, vHi64, vLo64));
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS32:
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU32: {
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS16:
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU16: {
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS8:
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU8: {
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sad8Ux4: /* maybe we could do better?  ftm, do mkLazy2. */
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivS32:
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivU32:
3121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivU32E:
3122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivS32E:
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I32, vatom1, vatom2);
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivS64:
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_DivU64:
3127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivS64E:
3128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_DivU64E:
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazy2(mce, Ity_I64, vatom1, vatom2);
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32:
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveAddSub(mce,True,Ity_I32,
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   vatom1,vatom2, atom1,atom2);
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_AddSub32;
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32:
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveAddSub(mce,False,Ity_I32,
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   vatom1,vatom2, atom1,atom2);
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_AddSub32;
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cheap_AddSub32:
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32:
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpORD32S:
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpORD32U:
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpORD64S:
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpORD64U:
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return doCmpORD(mce, op, vatom1,vatom2, atom1,atom2);
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64:
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveAddSub(mce,True,Ity_I64,
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   vatom1,vatom2, atom1,atom2);
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_AddSub64;
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64:
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveAddSub(mce,False,Ity_I64,
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   vatom1,vatom2, atom1,atom2);
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_AddSub64;
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cheap_AddSub64:
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul64:
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLeft64(mce, mkUifU64(mce, vatom1,vatom2));
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul16:
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16:
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16:
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8:
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8:
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64:
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNE64:
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveCmpEQorNE(mce,Ity_I64, vatom1,vatom2, atom1,atom2 );
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_cmp64;
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cheap_cmp64:
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64S: case Iop_CmpLE64U:
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64U: case Iop_CmpLT64S:
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I1, mkUifU64(mce, vatom1,vatom2));
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32:
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNE32:
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mce->bogusLiterals)
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return expensiveCmpEQorNE(mce,Ity_I32, vatom1,vatom2, atom1,atom2 );
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto cheap_cmp32;
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cheap_cmp32:
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32S: case Iop_CmpLE32U:
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32U: case Iop_CmpLT32S:
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16: case Iop_CmpNE16:
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8: case Iop_CmpNE8:
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CasCmpEQ8:  case Iop_CasCmpNE8:
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CasCmpEQ16: case Iop_CasCmpNE16:
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CasCmpEQ32: case Iop_CasCmpNE32:
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CasCmpEQ64: case Iop_CasCmpNE64:
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Just say these all produce a defined result, regardless
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            of their arguments.  See COMMENT_ON_CasCmpEQ in this file. */
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I1, definedOfType(Ity_I1));
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl64: case Iop_Shr64: case Iop_Sar64:
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return scalarShift( mce, Ity_I64, op, vatom1,vatom2, atom1,atom2 );
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return scalarShift( mce, Ity_I32, op, vatom1,vatom2, atom1,atom2 );
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl16: case Iop_Shr16: case Iop_Sar16:
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return scalarShift( mce, Ity_I16, op, vatom1,vatom2, atom1,atom2 );
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl8: case Iop_Shr8:
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return scalarShift( mce, Ity_I8, op, vatom1,vatom2, atom1,atom2 );
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AndV128:
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifUV128; difd = mkDifDV128;
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_V128; improve = mkImproveANDV128; goto do_And_Or;
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And64:
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU64; difd = mkDifD64;
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I64; improve = mkImproveAND64; goto do_And_Or;
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And32:
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU32; difd = mkDifD32;
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And16:
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU16; difd = mkDifD16;
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And8:
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU8; difd = mkDifD8;
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_OrV128:
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifUV128; difd = mkDifDV128;
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_V128; improve = mkImproveORV128; goto do_And_Or;
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or64:
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU64; difd = mkDifD64;
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I64; improve = mkImproveOR64; goto do_And_Or;
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or32:
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU32; difd = mkDifD32;
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or16:
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU16; difd = mkDifD16;
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or8:
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         uifu = mkUifU8; difd = mkDifD8;
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_And_Or:
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assignNew(
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            'V', mce,
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            and_or_ty,
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            difd(mce, uifu(mce, vatom1, vatom2),
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      difd(mce, improve(mce, atom1, vatom1),
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                improve(mce, atom2, vatom2) ) ) );
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor8:
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU8(mce, vatom1, vatom2);
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor16:
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU16(mce, vatom1, vatom2);
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor32:
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU32(mce, vatom1, vatom2);
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor64:
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifU64(mce, vatom1, vatom2);
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_XorV128:
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkUifUV128(mce, vatom1, vatom2);
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIROp(op);
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:expr2vbits_Binop");
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* vatom = expr2vbits( mce, atom );
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,atom));
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt64Fx2:
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary64Fx2(mce, vatom);
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt64F0x2:
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary64F0x2(mce, vatom);
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt32Fx4:
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt32Fx4:
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32Fx4:
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32UtoFx4:
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32StoFx4:
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QFtoI32Ux4_RZ:
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QFtoI32Sx4_RZ:
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32x4_RM:
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32x4_RP:
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32x4_RN:
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF32x4_RZ:
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32x4:
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs32Fx4:
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Neg32Fx4:
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rsqrte32Fx4:
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary32Fx4(mce, vatom);
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32UtoFx2:
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32StoFx2:
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32Fx2:
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32x2:
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs32Fx2:
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Neg32Fx2:
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rsqrte32Fx2:
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary32Fx2(mce, vatom);
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt32F0x4:
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt32F0x4:
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32F0x4:
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return unary32F0x4(mce, vatom);
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32UtoV128:
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64UtoV128:
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup8x16:
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup16x8:
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup32x4:
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse16_8x16:
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse32_8x16:
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse32_16x8:
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_8x16:
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_16x8:
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_32x4:
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_V128, unop(op, vatom));
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128HItoF64:  /* F128 -> high half of F128 */
3345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return assignNew('V', mce, Ity_I64, unop(Iop_128HIto64, vatom));
3346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F128LOtoF64:  /* F128 -> low  half of F128 */
3347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return assignNew('V', mce, Ity_I64, unop(Iop_128to64, vatom));
3348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NegF128:
3350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_AbsF128:
3351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkPCastTo(mce, Ity_I128, vatom);
3352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I32StoF128: /* signed I32 -> F128 */
3354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64StoF128: /* signed I64 -> F128 */
3355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F32toF128:  /* F32 -> F128 */
3356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_F64toF128:  /* F64 -> F128 */
3357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mkPCastTo(mce, Ity_I128, vatom);
3358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_F32toF64:
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32StoF64:
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_I32UtoF64:
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NegF64:
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AbsF64:
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Est5FRSqrt:
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF64_NEAREST:
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF64_NegINF:
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF64_PosINF:
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RoundF64toF64_ZERO:
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz64:
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Ctz64:
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I64, vatom);
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz32:
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Ctz32:
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_TruncF64asF32:
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NegF32:
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AbsF32:
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I32, vatom);
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Uto64:
3381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_1Sto64:
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto64:
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto64:
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Uto64:
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Sto64:
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Sto64:
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Uto64:
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to64:
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128HIto64:
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_128HIto64:
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_128to64:
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup8x8:
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup16x4:
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup32x2:
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse16_8x8:
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse32_8x8:
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse32_16x4:
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_8x8:
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_16x4:
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Reverse64_32x2:
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I64, unop(op, vatom));
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I16StoF32:
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to32:
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HIto32:
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Uto32:
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto32:
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto32:
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Uto32:
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Sto32:
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto32:
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to32:
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I32, unop(op, vatom));
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto16:
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto16:
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to16:
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32HIto16:
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to16:
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I16, unop(op, vatom));
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Uto8:
3423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_1Sto8:
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16to8:
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16HIto8:
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to8:
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to8:
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I8, unop(op, vatom));
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to1:
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I1, unop(Iop_32to1, vatom));
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to1:
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew('V', mce, Ity_I1, unop(Iop_64to1, vatom));
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF64asI64:
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpI64asF64:
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpI32asF32:
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF32asI32:
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NotV128:
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not64:
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not32:
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not16:
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not8:
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not1:
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return vatom;
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ8x8:
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cnt8x8:
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz8Sx8:
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls8Sx8:
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs8x8:
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x8(mce, vatom);
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ8x16:
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cnt8x16:
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz8Sx16:
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls8Sx16:
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs8x16:
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast8x16(mce, vatom);
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ16x4:
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz16Sx4:
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls16Sx4:
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs16x4:
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x4(mce, vatom);
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ16x8:
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz16Sx8:
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls16Sx8:
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs16x8:
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x8(mce, vatom);
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ32x2:
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz32Sx2:
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls32Sx2:
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_FtoI32Ux2_RZ:
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_FtoI32Sx2_RZ:
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs32x2:
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce, vatom);
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ32x4:
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz32Sx4:
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Cls32Sx4:
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_FtoI32Ux4_RZ:
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_FtoI32Sx4_RZ:
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Abs32x4:
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce, vatom);
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpwNEZ64:
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I64, vatom);
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ64x2:
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast64x2(mce, vatom);
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn16to8x8:
3497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn32to16x4:
3498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowUn64to32x2:
3499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Sx8:
3500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Sto8Ux8:
3501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn16Uto8Ux8:
3502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Sx4:
3503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Sto16Ux4:
3504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn32Uto16Ux4:
3505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Sx2:
3506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Sto32Ux2:
3507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowUn64Uto32Ux2:
3508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorNarrowUnV128(mce, op, vatom);
3509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen8Sto16x8:
3511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen8Uto16x8:
3512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen16Sto32x4:
3513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen16Uto32x4:
3514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen32Sto64x2:
3515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Widen32Uto64x2:
3516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return vectorWidenI64(mce, op, vatom);
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL32Ux2:
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL32Sx2:
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCastTo(mce, Ity_I64,
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_I64, unop(op, mkPCast32x2(mce, vatom))));
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL16Ux4:
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL16Sx4:
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x2(mce,
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_I64, unop(op, mkPCast16x4(mce, vatom))));
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL8Ux8:
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL8Sx8:
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x4(mce,
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_I64, unop(op, mkPCast8x8(mce, vatom))));
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL32Ux4:
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL32Sx4:
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast64x2(mce,
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, unop(op, mkPCast32x4(mce, vatom))));
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL16Ux8:
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL16Sx8:
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast32x4(mce,
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, unop(op, mkPCast16x8(mce, vatom))));
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL8Ux16:
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_PwAddL8Sx16:
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkPCast16x8(mce,
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assignNew('V', mce, Ity_V128, unop(op, mkPCast8x16(mce, vatom))));
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I64UtoF32:
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIROp(op);
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:expr2vbits_Unop");
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Worker function; do not call directly. */
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expr2vbits_Load_WRK ( MCEnv* mce,
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IREndness end, IRType ty,
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRAtom* addr, UInt bias )
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*    helper;
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char*    hname;
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp   datavbits;
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  addrAct;
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,addr));
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(end == Iend_LE || end == Iend_BE);
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First, emit a definedness test for the address.  This also sets
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the address (shadow) to 'defined' following the test. */
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complainIfUndefined( mce, addr );
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now cook up a call to the relevant helper function, to read the
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      data V bits from shadow memory. */
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = shadowTypeV(ty);
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (end == Iend_LE) {
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I64: helper = &MC_(helperc_LOADV64le);
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_LOADV64le)";
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32: helper = &MC_(helperc_LOADV32le);
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_LOADV32le)";
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16: helper = &MC_(helperc_LOADV16le);
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_LOADV16le)";
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:  helper = &MC_(helperc_LOADV8);
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_LOADV8)";
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:      ppIRType(ty);
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VG_(tool_panic)("memcheck:do_shadow_Load(LE)");
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I64: helper = &MC_(helperc_LOADV64be);
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_LOADV64be)";
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32: helper = &MC_(helperc_LOADV32be);
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_LOADV32be)";
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16: helper = &MC_(helperc_LOADV16be);
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_LOADV16be)";
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:  helper = &MC_(helperc_LOADV8);
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_LOADV8)";
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:      ppIRType(ty);
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VG_(tool_panic)("memcheck:do_shadow_Load(BE)");
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Generate the actual address into addrAct. */
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bias == 0) {
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addrAct = addr;
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp    mkAdd;
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom* eBias;
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType  tyAddr  = mce->hWordTy;
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mkAdd   = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eBias   = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addrAct = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBias) );
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We need to have a place to park the V bits we're just about to
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      read. */
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   datavbits = newTemp(mce, ty, VSh);
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_1_N( datavbits,
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           1/*regparms*/,
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           hname, VG_(fnptr_to_fnentry)( helper ),
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkIRExprVec_1( addrAct ));
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setHelperAnns( mce, di );
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'V', mce, IRStmt_Dirty(di) );
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkexpr(datavbits);
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expr2vbits_Load ( MCEnv* mce,
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IREndness end, IRType ty,
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* addr, UInt bias )
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *v64hi, *v64lo;
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(end == Iend_LE || end == Iend_BE);
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (shadowTypeV(ty)) {
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Load_WRK(mce, end, ty, addr, bias);
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128:
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (end == Iend_LE) {
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return assignNew( 'V', mce,
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Ity_V128,
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_64HLtoV128, v64hi, v64lo));
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("expr2vbits_Load");
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRAtom* expr2vbits_Mux0X ( MCEnv* mce,
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vbitsC, *vbits0, *vbitsX;
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty;
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Given Mux0X(cond,expr0,exprX), generate
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      That is, steer the V bits like the originals, but trash the
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      result if the steering value is undefined.  This gives
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lazy propagation. */
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cond));
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, expr0));
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, exprX));
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vbitsC = expr2vbits(mce, cond);
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vbits0 = expr2vbits(mce, expr0);
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vbitsX = expr2vbits(mce, exprX);
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = typeOfIRExpr(mce->sb->tyenv, vbits0);
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mkUifU(mce, ty, assignNew('V', mce, ty,
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     IRExpr_Mux0X(cond, vbits0, vbitsX)),
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkPCastTo(mce, ty, vbitsC) );
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- This is the main expression-handling function. --------- */
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return shadow_GETI( mce, e->Iex.GetI.descr,
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  e->Iex.GetI.ix, e->Iex.GetI.bias );
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return IRExpr_RdTmp( findShadowTmpV(mce, e->Iex.RdTmp.tmp) );
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return definedOfType(shadowTypeV(typeOfIRExpr(mce->sb->tyenv, e)));
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Qop(
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Qop.op,
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Qop.arg1, e->Iex.Qop.arg2,
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   e->Iex.Qop.arg3, e->Iex.Qop.arg4
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Triop(
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Triop.op,
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Triop.arg1, e->Iex.Triop.arg2, e->Iex.Triop.arg3
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Binop(
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce,
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Binop.op,
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.Binop.arg1, e->Iex.Binop.arg2
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Load( mce, e->Iex.Load.end,
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      e->Iex.Load.ty,
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      e->Iex.Load.addr, 0/*addr bias*/ );
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkLazyN( mce, e->Iex.CCall.args,
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              e->Iex.CCall.retty,
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              e->Iex.CCall.cee );
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       e->Iex.Mux0X.exprX);
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(e);
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck: expr2vbits");
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Generate shadow stmts from all kinds of IRStmts.     ---*/
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Widen a value to the host word size. */
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty, tyH;
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* vatom is vbits-value and as such can only have a shadow type. */
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vatom));
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty  = typeOfIRExpr(mce->sb->tyenv, vatom);
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tyH = mce->hWordTy;
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tyH == Ity_I32) {
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32:
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return vatom;
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16:
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_16Uto32, vatom));
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_8Uto32, vatom));
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto unhandled;
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tyH == Ity_I64) {
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32:
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_32Uto64, vatom));
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16:
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_32Uto64,
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I32, unop(Iop_16Uto32, vatom))));
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return assignNew('V', mce, tyH, unop(Iop_32Uto64,
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   assignNew('V', mce, Ity_I32, unop(Iop_8Uto32, vatom))));
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto unhandled;
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto unhandled;
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unhandled:
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(tool_panic)("zwidenToHostWord");
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a shadow store.  addr is always the original address atom.
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You can pass in either originals or V-bits for the data atom, but
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   obviously not both.  guard :: Ity_I1 controls whether the store
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   really happens; NULL means it unconditionally does.  Note that
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guard itself is not checked for definedness; the caller of this
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   function must do that if necessary. */
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_shadow_Store ( MCEnv* mce,
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IREndness end,
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRAtom* addr, UInt bias,
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRAtom* data, IRAtom* vdata,
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRAtom* guard )
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp     mkAdd;
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   ty, tyAddr;
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*    helper = NULL;
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char*    hname = NULL;
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* c;
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tyAddr = mce->hWordTy;
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mkAdd  = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( end == Iend_LE || end == Iend_BE );
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (data) {
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(!vdata);
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, data));
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(bias == 0);
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vdata = expr2vbits( mce, data );
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(vdata);
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce,addr));
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce,vdata));
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) {
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, guard));
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(typeOfIRExpr(mce->sb->tyenv, guard) == Ity_I1);
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = typeOfIRExpr(mce->sb->tyenv, vdata);
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // If we're not doing undefined value checking, pretend that this value
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // is "all valid".  That lets Vex's optimiser remove some of the V bit
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // shadow computation ops that precede it.
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) == 1) {
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_V128: // V128 weirdness
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        c = IRConst_V128(V_BITS16_DEFINED); break;
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I64:  c = IRConst_U64 (V_BITS64_DEFINED); break;
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32:  c = IRConst_U32 (V_BITS32_DEFINED); break;
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16:  c = IRConst_U16 (V_BITS16_DEFINED); break;
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:   c = IRConst_U8  (V_BITS8_DEFINED);  break;
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:       VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vdata = IRExpr_Const( c );
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First, emit a definedness test for the address.  This also sets
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the address (shadow) to 'defined' following the test. */
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complainIfUndefined( mce, addr );
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now decide which helper function to call to write the data V
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bits into shadow memory. */
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (end == Iend_LE) {
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_V128: /* we'll use the helper twice */
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I64: helper = &MC_(helperc_STOREV64le);
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV64le)";
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32: helper = &MC_(helperc_STOREV32le);
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV32le)";
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16: helper = &MC_(helperc_STOREV16le);
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV16le)";
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:  helper = &MC_(helperc_STOREV8);
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV8)";
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:      VG_(tool_panic)("memcheck:do_shadow_Store(LE)");
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ty) {
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_V128: /* we'll use the helper twice */
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I64: helper = &MC_(helperc_STOREV64be);
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV64be)";
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32: helper = &MC_(helperc_STOREV32be);
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV32be)";
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16: helper = &MC_(helperc_STOREV16be);
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV16be)";
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:  helper = &MC_(helperc_STOREV8);
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hname = "MC_(helperc_STOREV8)";
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       break;
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:      VG_(tool_panic)("memcheck:do_shadow_Store(BE)");
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ty == Ity_V128) {
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V128-bit case */
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* See comment in next clause re 64-bit regparms */
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* also, need to be careful about endianness */
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int     offLo64, offHi64;
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty *diLo64, *diHi64;
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom  *addrLo64, *addrHi64;
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom  *vdataLo64, *vdataHi64;
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom  *eBiasLo64, *eBiasHi64;
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (end == Iend_LE) {
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         offLo64 = 0;
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         offHi64 = 8;
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         offLo64 = 8;
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         offHi64 = 0;
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eBiasLo64 = tyAddr==Ity_I32 ? mkU32(bias+offLo64) : mkU64(bias+offLo64);
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addrLo64  = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasLo64) );
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vdataLo64 = assignNew('V', mce, Ity_I64, unop(Iop_V128to64, vdata));
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      diLo64    = unsafeIRDirty_0_N(
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     1/*regparms*/,
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hname, VG_(fnptr_to_fnentry)( helper ),
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkIRExprVec_2( addrLo64, vdataLo64 )
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eBiasHi64 = tyAddr==Ity_I32 ? mkU32(bias+offHi64) : mkU64(bias+offHi64);
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addrHi64  = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBiasHi64) );
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vdataHi64 = assignNew('V', mce, Ity_I64, unop(Iop_V128HIto64, vdata));
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      diHi64    = unsafeIRDirty_0_N(
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     1/*regparms*/,
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hname, VG_(fnptr_to_fnentry)( helper ),
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkIRExprVec_2( addrHi64, vdataHi64 )
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard) diLo64->guard = guard;
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard) diHi64->guard = guard;
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setHelperAnns( mce, diLo64 );
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setHelperAnns( mce, diHi64 );
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'V', mce, IRStmt_Dirty(diLo64) );
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'V', mce, IRStmt_Dirty(diHi64) );
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty *di;
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom  *addrAct;
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 8/16/32/64-bit cases */
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate the actual address into addrAct. */
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bias == 0) {
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addrAct = addr;
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* eBias   = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addrAct = assignNew('V', mce, tyAddr, binop(mkAdd, addr, eBias));
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We can't do this with regparm 2 on 32-bit platforms, since
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the back ends aren't clever enough to handle 64-bit
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparm args.  Therefore be different. */
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         di = unsafeIRDirty_0_N(
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 1/*regparms*/,
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 hname, VG_(fnptr_to_fnentry)( helper ),
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkIRExprVec_2( addrAct, vdata )
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         di = unsafeIRDirty_0_N(
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 2/*regparms*/,
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 hname, VG_(fnptr_to_fnentry)( helper ),
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkIRExprVec_2( addrAct,
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                zwidenToHostWord( mce, vdata ))
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard) di->guard = guard;
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setHelperAnns( mce, di );
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'V', mce, IRStmt_Dirty(di) );
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do lazy pessimistic propagation through a dirty helper call, by
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   looking at the annotations on it.  This is the most complex part of
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Memcheck. */
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRType szToITy ( Int n )
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (n) {
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return Ity_I8;
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return Ity_I16;
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: return Ity_I32;
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: return Ity_I64;
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: VG_(tool_panic)("szToITy(memcheck)");
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int       i, n, toDo, gSz, gOff;
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom    *src, *here, *curr;
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType    tySrc, tyDst;
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp    dst;
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IREndness end;
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* What's the native endianness?  We need to know this. */
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VG_BIGENDIAN)
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end = Iend_BE;
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VG_LITTLEENDIAN)
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end = Iend_LE;
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#    error "Unknown endianness"
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First check the guard. */
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complainIfUndefined(mce, d->guard);
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now round up all inputs and PCast over them. */
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   curr = definedOfType(Ity_I32);
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: unmasked args */
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; d->args[i]; i++) {
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->cee->mcx_mask & (1<<i)) {
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ignore this arg */
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = mkUifU32(mce, here, curr);
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: guest state that we read. */
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < d->nFxState; i++) {
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->fxState[i].fx != Ifx_None);
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->fxState[i].fx == Ifx_Write)
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ignore any sections marked as 'always defined'. */
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0)
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     d->fxState[i].offset, d->fxState[i].size );
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This state element is read or modified.  So we need to
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         consider it.  If larger than 8 bytes, deal with it in 8-byte
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         chunks. */
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gSz  = d->fxState[i].size;
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gOff = d->fxState[i].offset;
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(gSz > 0);
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) {
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (gSz == 0) break;
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n = gSz <= 8 ? gSz : 8;
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* update 'curr' with UifU of the state slice
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gOff .. gOff+n-1 */
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tySrc = szToITy( n );
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         src   = assignNew( 'V', mce, tySrc,
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 shadow_GET(mce, gOff, tySrc ) );
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = mkPCastTo( mce, Ity_I32, src );
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = mkUifU32(mce, here, curr);
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gSz -= n;
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gOff += n;
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: memory.  First set up some info needed regardless of
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      whether we're doing reads or writes. */
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx != Ifx_None) {
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Because we may do multiple shadow loads/stores from the same
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base address, it's best to do a single test of its
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         definedness right now.  Post-instrumentation optimisation
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         should remove all but this test. */
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType tyAddr;
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->mAddr);
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      complainIfUndefined(mce, d->mAddr);
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tyAddr = typeOfIRExpr(mce->sb->tyenv, d->mAddr);
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(tyAddr == mce->hWordTy); /* not really right */
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with memory inputs (reads or modifies) */
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toDo   = d->mSize;
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 32-bit chunks.  We don't care about the endianness
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         since it's all going to be condensed down to a single bit,
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         but nevertheless choose an endianness which is hopefully
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         native to the platform. */
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 4) {
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = mkPCastTo(
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce, Ity_I32,
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expr2vbits_Load ( mce, end, Ity_I32,
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     d->mAddr, d->mSize - toDo )
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = mkUifU32(mce, here, curr);
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 4;
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 16-bit chunks */
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 2) {
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = mkPCastTo(
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mce, Ity_I32,
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expr2vbits_Load ( mce, end, Ity_I16,
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     d->mAddr, d->mSize - toDo )
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = mkUifU32(mce, here, curr);
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 2;
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(toDo == 0); /* also need to handle 1-byte excess */
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Whew!  So curr is a 32-bit V-value summarising pessimistically
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      all the inputs to the helper.  Now we need to re-distribute the
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      results to all destinations. */
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: the destination temporary, if there is one. */
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->tmp != IRTemp_INVALID) {
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst   = findShadowTmpV(mce, d->tmp);
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tyDst = typeOfIRTemp(mce->sb->tyenv, d->tmp);
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'V', mce, dst, mkPCastTo( mce, tyDst, curr) );
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: guest state that we write or modify. */
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < d->nFxState; i++) {
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->fxState[i].fx != Ifx_None);
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->fxState[i].fx == Ifx_Read)
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ignore any sections marked as 'always defined'. */
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This state element is written or modified.  So we need to
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         consider it.  If larger than 8 bytes, deal with it in 8-byte
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         chunks. */
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gSz  = d->fxState[i].size;
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gOff = d->fxState[i].offset;
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(gSz > 0);
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) {
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (gSz == 0) break;
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n = gSz <= 8 ? gSz : 8;
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Write suitably-casted 'curr' to the state slice
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gOff .. gOff+n-1 */
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tyDst = szToITy( n );
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_shadow_PUT( mce, gOff,
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             NULL, /* original atom */
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkPCastTo( mce, tyDst, curr ) );
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gSz -= n;
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gOff += n;
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: memory that we write or modify.  Same comments about
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      endianness as above apply. */
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toDo   = d->mSize;
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 32-bit chunks */
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 4) {
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          NULL, /* original data */
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkPCastTo( mce, Ity_I32, curr ),
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          NULL/*guard*/ );
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 4;
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 16-bit chunks */
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 2) {
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          NULL, /* original data */
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkPCastTo( mce, Ity_I16, curr ),
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          NULL/*guard*/ );
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 2;
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(toDo == 0); /* also need to handle 1-byte excess */
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* We have an ABI hint telling us that [base .. base+len-1] is to
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   become undefined ("writable").  Generate code to call a helper to
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notify the A/V bit machinery of this fact.
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We call
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len,
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    Addr nia );
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_AbiHint ( MCEnv* mce, IRExpr* base, Int len, IRExpr* nia )
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Minor optimisation: if not doing origin tracking, ignore the
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      supplied nia and pass zero instead.  This is on the basis that
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(helperc_MAKE_STACK_UNINIT) will ignore it anyway, and we can
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      almost always generate a shorter instruction to put zero into a
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register than any other value. */
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_mc_level) < 3)
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nia = mkIRExpr_HWord(0);
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_0_N(
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           0/*regparms*/,
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "MC_(helperc_MAKE_STACK_UNINIT)",
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           VG_(fnptr_to_fnentry)( &MC_(helperc_MAKE_STACK_UNINIT) ),
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           mkIRExprVec_3( base, mkIRExpr_HWord( (UInt)len), nia )
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'V', mce, IRStmt_Dirty(di) );
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ Dealing with IRCAS (big and complex) ------ */
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* FWDS */
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* gen_load_b  ( MCEnv* mce, Int szB,
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* baseaddr, Int offset );
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* gen_maxU32  ( MCEnv* mce, IRAtom* b1, IRAtom* b2 );
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void    gen_store_b ( MCEnv* mce, Int szB,
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* baseaddr, Int offset, IRAtom* dataB,
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRAtom* guard );
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_CAS_single ( MCEnv* mce, IRCAS* cas );
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_CAS_double ( MCEnv* mce, IRCAS* cas );
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Either ORIG and SHADOW are both IRExpr.RdTmps, or they are both
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr.Consts, else this asserts.  If they are both Consts, it
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   doesn't do anything.  So that just leaves the RdTmp case.
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In which case: this assigns the shadow value SHADOW to the IR
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shadow temporary associated with ORIG.  That is, ORIG, being an
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   original temporary, will have a shadow temporary associated with
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it.  However, in the case envisaged here, there will so far have
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   been no IR emitted to actually write a shadow value into that
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   temporary.  What this routine does is to (emit IR to) copy the
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value in SHADOW into said temporary, so that after this call,
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr.RdTmps of ORIG's shadow temp will correctly pick up the
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value in SHADOW.
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Point is to allow callers to compute "by hand" a shadow value for
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ORIG, and force it to be associated with ORIG.
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   How do we know that that shadow associated with ORIG has not so far
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   been assigned to?  Well, we don't per se know that, but supposing
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it had.  Then this routine would create a second assignment to it,
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and later the IR sanity checker would barf.  But that never
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   happens.  QED.
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bind_shadow_tmp_to_orig ( UChar how,
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      MCEnv* mce,
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      IRAtom* orig, IRAtom* shadow )
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, orig));
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, shadow));
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (orig->tag) {
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(shadow->tag == Iex_Const);
4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(shadow->tag == Iex_RdTmp);
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (how == 'V') {
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign('V', mce, findShadowTmpV(mce,orig->Iex.RdTmp.tmp),
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   shadow);
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(how == 'B');
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign('B', mce, findShadowTmpB(mce,orig->Iex.RdTmp.tmp),
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   shadow);
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_shadow_CAS ( MCEnv* mce, IRCAS* cas )
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scheme is (both single- and double- cases):
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      1. fetch data#,dataB (the proposed new value)
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      2. fetch expd#,expdB (what we expect to see at the address)
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      3. check definedness of address
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      4. load old#,oldB from shadow memory; this also checks
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addressibility of the address
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      5. the CAS itself
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      6. compute "expected == old".  See COMMENT_ON_CasCmpEQ below.
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      7. if "expected == old" (as computed by (6))
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            store data#,dataB to shadow memory
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Note that 5 reads 'old' but 4 reads 'old#'.  Similarly, 5 stores
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'data' but 7 stores 'data#'.  Hence it is possible for the
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shadow data to be incorrectly checked and/or updated:
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * 7 is at least gated correctly, since the 'expected == old'
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        condition is derived from outputs of 5.  However, the shadow
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        write could happen too late: imagine after 5 we are
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        descheduled, a different thread runs, writes a different
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (shadow) value at the address, and then we resume, hence
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        overwriting the shadow value written by the other thread.
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Because the original memory access is atomic, there's no way to
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      make both the original and shadow accesses into a single atomic
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thing, hence this is unavoidable.
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      At least as Valgrind stands, I don't think it's a problem, since
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      we're single threaded *and* we guarantee that there are no
4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      context switches during the execution of any specific superblock
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      -- context switches can only happen at superblock boundaries.
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If Valgrind ever becomes MT in the future, then it might be more
4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of a problem.  A possible kludge would be to artificially
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      associate with the location, a lock, which we must acquire and
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      release around the transaction as a whole.  Hmm, that probably
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      would't work properly since it only guards us against other
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      threads doing CASs on the same location, not against other
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      threads doing normal reads and writes.
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ------------------------------------------------------------
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      COMMENT_ON_CasCmpEQ:
4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Note two things.  Firstly, in the sequence above, we compute
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "expected == old", but we don't check definedness of it.  Why
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not?  Also, the x86 and amd64 front ends use
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Iop_CmpCas{EQ,NE}{8,16,32,64} comparisons to make the equivalent
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      determination (expected == old ?) for themselves, and we also
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      don't check definedness for those primops; we just say that the
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      result is defined.  Why?  Details follow.
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      x86/amd64 contains various forms of locked insns:
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * lock prefix before all basic arithmetic insn;
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        eg lock xorl %reg1,(%reg2)
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * atomic exchange reg-mem
4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * compare-and-swaps
4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Rather than attempt to represent them all, which would be a
4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      royal PITA, I used a result from Maurice Herlihy
4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (http://en.wikipedia.org/wiki/Maurice_Herlihy), in which he
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      demonstrates that compare-and-swap is a primitive more general
4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      than the other two, and so can be used to represent all of them.
4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      So the translation scheme for (eg) lock incl (%reg) is as
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      follows:
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        again:
4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         old = * %reg
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         new = old + 1
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         atomically { if (* %reg == old) { * %reg = new } else { goto again } }
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The "atomically" is the CAS bit.  The scheme is always the same:
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      get old value from memory, compute new value, atomically stuff
4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new value back in memory iff the old value has not changed (iow,
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      no other thread modified it in the meantime).  If it has changed
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      then we've been out-raced and we have to start over.
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Now that's all very neat, but it has the bad side effect of
4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      introducing an explicit equality test into the translation.
4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Consider the behaviour of said code on a memory location which
4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is uninitialised.  We will wind up doing a comparison on
4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uninitialised data, and mc duly complains.
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      What's difficult about this is, the common case is that the
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      location is uncontended, and so we're usually comparing the same
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      value (* %reg) with itself.  So we shouldn't complain even if it
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is undefined.  But mc doesn't know that.
4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      My solution is to mark the == in the IR specially, so as to tell
4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mc that it almost certainly compares a value with itself, and we
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      should just regard the result as always defined.  Rather than
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add a bit to all IROps, I just cloned Iop_CmpEQ{8,16,32,64} into
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Iop_CasCmpEQ{8,16,32,64} so as not to disturb anything else.
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      So there's always the question of, can this give a false
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      negative?  eg, imagine that initially, * %reg is defined; and we
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      read that; but then in the gap between the read and the CAS, a
4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      different thread writes an undefined (and different) value at
4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the location.  Then the CAS in this thread will fail and we will
4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      go back to "again:", but without knowing that the trip back
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      there was based on an undefined comparison.  No matter; at least
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the other thread won the race and the location is correctly
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      marked as undefined.  What if it wrote an uninitialised version
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of the same value that was there originally, though?
4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      etc etc.  Seems like there's a small corner case in which we
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      might lose the fact that something's defined -- we're out-raced
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in between the "old = * reg" and the "atomically {", _and_ the
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      other thread is writing in an undefined version of what's
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      already there.  Well, that seems pretty unlikely.
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ---
4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If we ever need to reinstate it .. code which generates a
4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      definedness test for "expected == old" was removed at r10432 of
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this file.
4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cas->oldHi == IRTemp_INVALID) {
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_shadow_CAS_single( mce, cas );
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_shadow_CAS_double( mce, cas );
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_CAS_single ( MCEnv* mce, IRCAS* cas )
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vdataLo = NULL, *bdataLo = NULL;
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vexpdLo = NULL, *bexpdLo = NULL;
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *voldLo  = NULL, *boldLo  = NULL;
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *expd_eq_old = NULL;
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opCasCmpEQ;
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    elemSzB;
4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType elemTy;
4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   otrak = MC_(clo_mc_level) >= 3; /* a shorthand */
4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* single CAS */
4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->oldHi == IRTemp_INVALID);
4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->expdHi == NULL);
4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->dataHi == NULL);
4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   elemTy = typeOfIRExpr(mce->sb->tyenv, cas->expdLo);
4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (elemTy) {
4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:  elemSzB = 1; opCasCmpEQ = Iop_CasCmpEQ8;  break;
4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16: elemSzB = 2; opCasCmpEQ = Iop_CasCmpEQ16; break;
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32: elemSzB = 4; opCasCmpEQ = Iop_CasCmpEQ32; break;
4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64: elemSzB = 8; opCasCmpEQ = Iop_CasCmpEQ64; break;
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: tl_assert(0); /* IR defn disallows any other types */
4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 1. fetch data# (the proposed new value) */
4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->dataLo));
4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vdataLo
4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->dataLo));
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vdataLo));
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bdataLo
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->dataLo));
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bdataLo));
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 2. fetch expected# (what we expect to see at the address) */
4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->expdLo));
4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vexpdLo
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->expdLo));
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vexpdLo));
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bexpdLo
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->expdLo));
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bexpdLo));
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 3. check definedness of address */
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 4. fetch old# from shadow memory; this also checks
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addressibility of the address */
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   voldLo
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew(
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           'V', mce, elemTy,
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           expr2vbits_Load(
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mce,
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              cas->end, elemTy, cas->addr, 0/*Addr bias*/
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ));
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bind_shadow_tmp_to_orig('V', mce, mkexpr(cas->oldLo), voldLo);
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      boldLo
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32,
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     gen_load_b(mce, elemSzB, cas->addr, 0/*addr bias*/));
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bind_shadow_tmp_to_orig('B', mce, mkexpr(cas->oldLo), boldLo);
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 5. the CAS itself */
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'C', mce, IRStmt_CAS(cas) );
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 6. compute "expected == old" */
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* See COMMENT_ON_CasCmpEQ in this file background/rationale. */
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note that 'C' is kinda faking it; it is indeed a non-shadow
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tree, but it's not copied from the input block. */
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expd_eq_old
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('C', mce, Ity_I1,
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(opCasCmpEQ, cas->expdLo, mkexpr(cas->oldLo)));
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 7. if "expected == old"
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            store data# to shadow memory */
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_shadow_Store( mce, cas->end, cas->addr, 0/*bias*/,
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    NULL/*data*/, vdataLo/*vdata*/,
4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expd_eq_old/*guard for store*/ );
4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
4506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gen_store_b( mce, elemSzB, cas->addr, 0/*offset*/,
4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   bdataLo/*bdata*/,
4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expd_eq_old/*guard for store*/ );
4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_CAS_double ( MCEnv* mce, IRCAS* cas )
4514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vdataHi = NULL, *bdataHi = NULL;
4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vdataLo = NULL, *bdataLo = NULL;
4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vexpdHi = NULL, *bexpdHi = NULL;
4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *vexpdLo = NULL, *bexpdLo = NULL;
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *voldHi  = NULL, *boldHi  = NULL;
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *voldLo  = NULL, *boldLo  = NULL;
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *xHi = NULL, *xLo = NULL, *xHL = NULL;
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom *expd_eq_old = NULL, *zero = NULL;
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   opCasCmpEQ, opOr, opXor;
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    elemSzB, memOffsLo, memOffsHi;
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType elemTy;
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   otrak = MC_(clo_mc_level) >= 3; /* a shorthand */
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* double CAS */
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->oldHi != IRTemp_INVALID);
4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->expdHi != NULL);
4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cas->dataHi != NULL);
4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   elemTy = typeOfIRExpr(mce->sb->tyenv, cas->expdLo);
4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (elemTy) {
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCasCmpEQ = Iop_CasCmpEQ8; opOr = Iop_Or8; opXor = Iop_Xor8;
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         elemSzB = 1; zero = mkU8(0);
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCasCmpEQ = Iop_CasCmpEQ16; opOr = Iop_Or16; opXor = Iop_Xor16;
4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         elemSzB = 2; zero = mkU16(0);
4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCasCmpEQ = Iop_CasCmpEQ32; opOr = Iop_Or32; opXor = Iop_Xor32;
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         elemSzB = 4; zero = mkU32(0);
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opCasCmpEQ = Iop_CasCmpEQ64; opOr = Iop_Or64; opXor = Iop_Xor64;
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         elemSzB = 8; zero = mkU64(0);
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0); /* IR defn disallows any other types */
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 1. fetch data# (the proposed new value) */
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->dataHi));
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->dataLo));
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vdataHi
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->dataHi));
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vdataLo
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->dataLo));
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vdataHi));
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vdataLo));
4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bdataHi
4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->dataHi));
4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bdataLo
4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->dataLo));
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bdataHi));
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bdataLo));
4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 2. fetch expected# (what we expect to see at the address) */
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->expdHi));
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isOriginalAtom(mce, cas->expdLo));
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vexpdHi
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->expdHi));
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vexpdLo
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('V', mce, elemTy, expr2vbits(mce, cas->expdLo));
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vexpdHi));
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isShadowAtom(mce, vexpdLo));
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bexpdHi
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->expdHi));
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bexpdLo
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32, schemeE(mce, cas->expdLo));
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bexpdHi));
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isShadowAtom(mce, bexpdLo));
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 3. check definedness of address */
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 4. fetch old# from shadow memory; this also checks
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addressibility of the address */
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cas->end == Iend_LE) {
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memOffsLo = 0;
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memOffsHi = elemSzB;
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(cas->end == Iend_BE);
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memOffsLo = elemSzB;
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memOffsHi = 0;
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   voldHi
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew(
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           'V', mce, elemTy,
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           expr2vbits_Load(
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mce,
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              cas->end, elemTy, cas->addr, memOffsHi/*Addr bias*/
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ));
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   voldLo
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew(
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           'V', mce, elemTy,
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           expr2vbits_Load(
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mce,
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              cas->end, elemTy, cas->addr, memOffsLo/*Addr bias*/
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ));
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bind_shadow_tmp_to_orig('V', mce, mkexpr(cas->oldHi), voldHi);
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bind_shadow_tmp_to_orig('V', mce, mkexpr(cas->oldLo), voldLo);
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      boldHi
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32,
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     gen_load_b(mce, elemSzB, cas->addr,
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                memOffsHi/*addr bias*/));
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      boldLo
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = assignNew('B', mce, Ity_I32,
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     gen_load_b(mce, elemSzB, cas->addr,
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                memOffsLo/*addr bias*/));
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bind_shadow_tmp_to_orig('B', mce, mkexpr(cas->oldHi), boldHi);
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bind_shadow_tmp_to_orig('B', mce, mkexpr(cas->oldLo), boldLo);
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 5. the CAS itself */
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'C', mce, IRStmt_CAS(cas) );
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 6. compute "expected == old" */
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* See COMMENT_ON_CasCmpEQ in this file background/rationale. */
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note that 'C' is kinda faking it; it is indeed a non-shadow
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tree, but it's not copied from the input block. */
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xHi = oldHi ^ expdHi;
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xLo = oldLo ^ expdLo;
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xHL = xHi | xLo;
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expd_eq_old = xHL == 0;
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xHi = assignNew('C', mce, elemTy,
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(opXor, cas->expdHi, mkexpr(cas->oldHi)));
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xLo = assignNew('C', mce, elemTy,
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(opXor, cas->expdLo, mkexpr(cas->oldLo)));
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xHL = assignNew('C', mce, elemTy,
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(opOr, xHi, xLo));
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expd_eq_old
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = assignNew('C', mce, Ity_I1,
4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(opCasCmpEQ, xHL, zero));
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 7. if "expected == old"
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            store data# to shadow memory */
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_shadow_Store( mce, cas->end, cas->addr, memOffsHi/*bias*/,
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    NULL/*data*/, vdataHi/*vdata*/,
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expd_eq_old/*guard for store*/ );
4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_shadow_Store( mce, cas->end, cas->addr, memOffsLo/*bias*/,
4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    NULL/*data*/, vdataLo/*vdata*/,
4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    expd_eq_old/*guard for store*/ );
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (otrak) {
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gen_store_b( mce, elemSzB, cas->addr, memOffsHi/*offset*/,
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   bdataHi/*bdata*/,
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expd_eq_old/*guard for store*/ );
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gen_store_b( mce, elemSzB, cas->addr, memOffsLo/*offset*/,
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   bdataLo/*bdata*/,
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expd_eq_old/*guard for store*/ );
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------ Dealing with LL/SC (not difficult) ------ */
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_shadow_LLSC ( MCEnv*    mce,
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IREndness stEnd,
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp    stResult,
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr*   stAddr,
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr*   stStoredata )
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* In short: treat a load-linked like a normal load followed by an
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignment of the loaded (shadow) data to the result temporary.
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Treat a store-conditional like a normal store, and mark the
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      result temporary as defined. */
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType resTy  = typeOfIRTemp(mce->sb->tyenv, stResult);
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp resTmp = findShadowTmpV(mce, stResult);
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(stAddr));
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (stStoredata)
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isIRAtom(stStoredata));
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (stStoredata == NULL) {
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Load Linked */
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Just treat this as a normal load, followed by an assignment of
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the value to .result. */
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Stay sane */
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(resTy == Ity_I64 || resTy == Ity_I32
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || resTy == Ity_I16 || resTy == Ity_I8);
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'V', mce, resTmp,
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   expr2vbits_Load(
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mce, stEnd, resTy, stAddr, 0/*addr bias*/));
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Store Conditional */
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Stay sane */
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType dataTy = typeOfIRExpr(mce->sb->tyenv,
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   stStoredata);
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(dataTy == Ity_I64 || dataTy == Ity_I32
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || dataTy == Ity_I16 || dataTy == Ity_I8);
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_shadow_Store( mce, stEnd,
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            stAddr, 0/* addr bias */,
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            stStoredata,
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            NULL /* shadow data */,
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            NULL/*guard*/ );
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is a store conditional, so it writes to .result a value
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         indicating whether or not the store succeeded.  Just claim
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this value is always defined.  In the PowerPC interpretation
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of store-conditional, definedness of the success indication
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         depends on whether the address of the store matches the
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reservation address.  But we can't tell that here (and
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         anyway, we're not being PowerPC-specific).  At least we are
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         guaranteed that the definedness of the store address, and its
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addressibility, will be checked as per normal.  So it seems
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pretty safe to just say that the success indication is always
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         defined.
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         In schemeS, for origin tracking, we must correspondingly set
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         a no-origin value for the origin shadow of .result.
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(resTy == Ity_I1);
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'V', mce, resTmp, definedOfType(resTy) );
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Memcheck main                                        ---*/
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void schemeS ( MCEnv* mce, IRStmt* st );
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isBogusAtom ( IRAtom* at )
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong n = 0;
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* con;
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(at));
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (at->tag == Iex_RdTmp)
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(at->tag == Iex_Const);
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   con = at->Iex.Const.con;
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (con->tag) {
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U1:   return False;
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U8:   n = (ULong)con->Ico.U8; break;
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U16:  n = (ULong)con->Ico.U16; break;
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U32:  n = (ULong)con->Ico.U32; break;
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U64:  n = (ULong)con->Ico.U64; break;
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_F64:  return False;
4757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ico_F32i: return False;
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_F64i: return False;
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_V128: return False;
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: ppIRExpr(at); tl_assert(0);
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VG_(printf)("%llx\n", n); */
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (/*32*/    n == 0xFEFEFEFFULL
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*32*/ || n == 0x80808080ULL
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*32*/ || n == 0x7F7F7F7FULL
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0xFFFFFFFFFEFEFEFFULL
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0xFEFEFEFEFEFEFEFFULL
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0x0000000000008080ULL
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0x8080808080808080ULL
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /*64*/ || n == 0x0101010101010101ULL
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          );
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i;
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*  e;
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* d;
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCAS*   cas;
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e = st->Ist.WrTmp.data;
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->tag) {
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Get:
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_RdTmp:
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Const:
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e);
4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Unop:
4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.Unop.arg);
4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_GetI:
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.GetI.ix);
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Binop:
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.Binop.arg1)
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || isBogusAtom(e->Iex.Binop.arg2);
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Triop:
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.Triop.arg1)
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || isBogusAtom(e->Iex.Triop.arg2)
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || isBogusAtom(e->Iex.Triop.arg3);
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Qop:
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.Qop.arg1)
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || isBogusAtom(e->Iex.Qop.arg2)
4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || isBogusAtom(e->Iex.Qop.arg3)
4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || isBogusAtom(e->Iex.Qop.arg4);
4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Mux0X:
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.Mux0X.cond)
4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || isBogusAtom(e->Iex.Mux0X.expr0)
4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || isBogusAtom(e->Iex.Mux0X.exprX);
4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_Load:
4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return isBogusAtom(e->Iex.Load.addr);
4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iex_CCall:
4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (i = 0; e->Iex.CCall.args[i]; i++)
4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (isBogusAtom(e->Iex.CCall.args[i]))
4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return True;
4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto unhandled;
4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = st->Ist.Dirty.details;
4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; d->args[i]; i++)
4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isBogusAtom(d->args[i]))
4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return True;
4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->guard && isBogusAtom(d->guard))
4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (d->mAddr && isBogusAtom(d->mAddr))
4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
4828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put:
4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.Put.data);
4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI:
4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.PutI.ix)
4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || isBogusAtom(st->Ist.PutI.data);
4834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
4835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.Store.addr)
4836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || isBogusAtom(st->Ist.Store.data);
4837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
4838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.Exit.guard);
4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.AbiHint.base)
4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || isBogusAtom(st->Ist.AbiHint.nia);
4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_CAS:
4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cas = st->Ist.CAS.details;
4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(cas->addr)
4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || (cas->expdHi ? isBogusAtom(cas->expdHi) : False)
4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || isBogusAtom(cas->expdLo)
4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || (cas->dataHi ? isBogusAtom(cas->dataHi) : False)
4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || isBogusAtom(cas->dataLo);
4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC:
4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return isBogusAtom(st->Ist.LLSC.addr)
4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                || (st->Ist.LLSC.storedata
4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ? isBogusAtom(st->Ist.LLSC.storedata)
4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       : False);
4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unhandled:
4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("hasBogusLiterals");
4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* MC_(instrument) ( VgCallbackClosure* closure,
4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRSB* sb_in,
4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        VexGuestLayout* layout,
4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        VexGuestExtents* vge,
4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRType gWordTy, IRType hWordTy )
4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    verboze = 0||False;
4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    bogus;
4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, j, first_stmt;
4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt* st;
4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MCEnv   mce;
4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB*   sb_out;
4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (gWordTy != hWordTy) {
4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We don't currently support this case. */
4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(tool_panic)("host/guest word size mismatch");
4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check we're not completely nuts */
4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(UWord)  == sizeof(void*));
4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Word)   == sizeof(void*));
4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Addr)   == sizeof(void*));
4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(ULong)  == 8);
4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Long)   == 8);
4890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Addr64) == 8);
4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(UInt)   == 4);
4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sizeof(Int)    == 4);
4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(MC_(clo_mc_level) >= 1 && MC_(clo_mc_level) <= 3);
4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up SB */
4897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sb_out = deepCopyIRSBExceptStmts(sb_in);
4898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up the running environment.  Both .sb and .tmpMap are
4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      modified as we go along.  Note that tmps are added to both
4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      .sb->tyenv and .tmpMap together, so the valid index-set for
4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      those two arrays should always be identical. */
4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(&mce, 0, sizeof(mce));
4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.sb             = sb_out;
4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.trace          = verboze;
4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.layout         = layout;
4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.hWordTy        = hWordTy;
4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.bogusLiterals  = False;
4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.tmpMap = VG_(newXA)( VG_(malloc), "mc.MC_(instrument).1", VG_(free),
4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            sizeof(TempMapEnt));
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < sb_in->tyenv->types_used; i++) {
4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TempMapEnt ent;
4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent.kind    = Orig;
4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent.shadowV = IRTemp_INVALID;
4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent.shadowB = IRTemp_INVALID;
4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(addToXA)( mce.tmpMap, &ent );
4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( VG_(sizeXA)( mce.tmpMap ) == sb_in->tyenv->types_used );
4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make a preliminary inspection of the statements, to see if there
4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      are any dodgy-looking literals.  If there are, we generate
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      extra-detailed (hence extra-expensive) instrumentation in
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      places.  Scan the whole bb even if dodgyness is found earlier,
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      so that the flatness assertion is applied to all stmts. */
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bogus = False;
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < sb_in->stmts_used; i++) {
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sb_in->stmts[i];
4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(st);
4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isFlatIRStmt(st));
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!bogus) {
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bogus = checkForBogusLiterals(st);
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0 && bogus) {
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("bogus: ");
4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mce.bogusLiterals = bogus;
4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy verbatim any IR preamble preceding the first IMark */
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(mce.sb == sb_out);
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(mce.sb != sb_in);
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = 0;
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (i < sb_in->stmts_used && sb_in->stmts[i]->tag != Ist_IMark) {
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sb_in->stmts[i];
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(st);
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isFlatIRStmt(st));
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( 'C', &mce, sb_in->stmts[i] );
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i++;
4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Nasty problem.  IR optimisation of the pre-instrumented IR may
4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cause the IR following the preamble to contain references to IR
4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      temporaries defined in the preamble.  Because the preamble isn't
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      instrumented, these temporaries don't have any shadows.
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Nevertheless uses of them following the preamble will cause
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memcheck to generate references to their shadows.  End effect is
4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to cause IR sanity check failures, due to references to
4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      non-existent shadows.  This is only evident for the complex
4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      preambles used for function wrapping on TOC-afflicted platforms
4973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      (ppc64-linux).
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The following loop therefore scans the preamble looking for
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignments to temporaries.  For each one found it creates an
4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignment to the corresponding (V) shadow temp, marking it as
4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'defined'.  This is the same resulting IR as if the main
4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      instrumentation loop before had been applied to the statement
4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'tmp = CONSTANT'.
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Similarly, if origin tracking is enabled, we must generate an
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignment for the corresponding origin (B) shadow, claiming
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      no-origin, as appropriate for a defined value.
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = 0; j < i; j++) {
4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sb_in->stmts[j]->tag == Ist_WrTmp) {
4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* findShadowTmpV checks its arg is an original tmp;
4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            no need to assert that here. */
4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp tmp_o = sb_in->stmts[j]->Ist.WrTmp.tmp;
4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp tmp_v = findShadowTmpV(&mce, tmp_o);
4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType ty_v  = typeOfIRTemp(sb_out->tyenv, tmp_v);
4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( 'V', &mce, tmp_v, definedOfType( ty_v ) );
4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (MC_(clo_mc_level) == 3) {
4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp tmp_b = findShadowTmpB(&mce, tmp_o);
4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(typeOfIRTemp(sb_out->tyenv, tmp_b) == Ity_I32);
4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( 'B', &mce, tmp_b, mkU32(0)/* UNKNOWN ORIGIN */);
4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) {
5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("create shadow tmp(s) for preamble tmp [%d] ty ", j);
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRType( ty_v );
5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Iterate over the remaining stmts to generate instrumentation. */
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sb_in->stmts_used > 0);
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(i >= 0);
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(i < sb_in->stmts_used);
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sb_in->stmts[i]->tag == Ist_IMark);
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (/* use current i*/; i < sb_in->stmts_used; i++) {
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sb_in->stmts[i];
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      first_stmt = sb_out->stmts_used;
5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (verboze) {
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (MC_(clo_mc_level) == 3) {
5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* See comments on case Ist_CAS below. */
5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->tag != Ist_CAS)
5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            schemeS( &mce, st );
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate instrumentation code for each stmt ... */
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_WrTmp:
5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( 'V', &mce, findShadowTmpV(&mce, st->Ist.WrTmp.tmp),
5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               expr2vbits( &mce, st->Ist.WrTmp.data) );
5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put:
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_PUT( &mce,
5042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           st->Ist.Put.offset,
5043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           st->Ist.Put.data,
5044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           NULL /* shadow atom */ );
5045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_PutI:
5048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_PUTI( &mce,
5049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.PutI.descr,
5050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.PutI.ix,
5051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.PutI.bias,
5052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.PutI.data );
5053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Store:
5056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_Store( &mce, st->Ist.Store.end,
5057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   st->Ist.Store.addr, 0/* addr bias */,
5058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   st->Ist.Store.data,
5059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   NULL /* shadow data */,
5060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   NULL/*guard*/ );
5061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Exit:
5064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            complainIfUndefined( &mce, st->Ist.Exit.guard );
5065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_IMark:
5068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_NoOp:
5071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_MBE:
5072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Dirty:
5075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_Dirty( &mce, st->Ist.Dirty.details );
5076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_AbiHint:
5079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_AbiHint( &mce, st->Ist.AbiHint.base,
5080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              st->Ist.AbiHint.len,
5081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              st->Ist.AbiHint.nia );
5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS:
5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_CAS( &mce, st->Ist.CAS.details );
5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note, do_shadow_CAS copies the CAS itself to the output
5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               block, because it needs to add instrumentation both
5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               before and after it.  Hence skip the copy below.  Also
5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               skip the origin-tracking stuff (call to schemeS) above,
5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               since that's all tangled up with it too; do_shadow_CAS
5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               does it all. */
5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_LLSC:
5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_shadow_LLSC( &mce,
5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.LLSC.end,
5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.LLSC.result,
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.LLSC.addr,
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            st->Ist.LLSC.storedata );
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(st);
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(tool_panic)("memcheck: unhandled IRStmt");
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* switch (st->tag) */
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 && verboze) {
5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = first_stmt; j < sb_out->stmts_used; j++) {
5112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("   ");
5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(sb_out->stmts[j]);
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("\n");
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ... and finally copy the stmt itself to the output.  Except,
5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         skip the copy of IRCASs; see comments on case Ist_CAS
5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         above. */
5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_CAS)
5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt('C', &mce, st);
5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now we need to complain if the jump target is undefined. */
5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   first_stmt = sb_out->stmts_used;
5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (verboze) {
5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("sb_in->next = ");
5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(sb_in->next);
5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n\n");
5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   complainIfUndefined( &mce, sb_in->next );
5136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0 && verboze) {
5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = first_stmt; j < sb_out->stmts_used; j++) {
5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("   ");
5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(sb_out->stmts[j]);
5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If this fails, there's been some serious snafu with tmp management,
5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that should be investigated. */
5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert( VG_(sizeXA)( mce.tmpMap ) == mce.sb->tyenv->types_used );
5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(deleteXA)( mce.tmpMap );
5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(mce.sb == sb_out);
5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sb_out;
5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
5156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Post-tree-build final tidying                        ---*/
5157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This exploits the observation that Memcheck often produces
5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   repeated conditional calls of the form
5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Dirty G MC_(helperc_value_check0/1/4/8_fail)(UInt otag)
5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with the same guard expression G guarding the same helper call.
5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The second and subsequent calls are redundant.  This usually
5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   results from instrumentation of guest code containing multiple
5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   memory references at different constant offsets from the same base
5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register.  After optimisation of the instrumentation, you get a
5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   test for the definedness of the base register for each memory
5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reference, which is kinda pointless.  MC_(final_tidy) therefore
5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   looks for such repeated calls and removes all but the first. */
5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A struct for recording which (helper, guard) pairs we have already
5174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   seen. */
5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct { void* entry; IRExpr* guard; }
5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Pair;
5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True if e1 and e2 definitely denote the same value (used to
5180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   compare guards).  Return False if unknown; False is the safe
5181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   answer.  Since guest registers and guest memory do not have the
5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SSA property we must return False if any Gets or Loads appear in
5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the expression. */
5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sameIRValue ( IRExpr* e1, IRExpr* e2 )
5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e1->tag != e2->tag)
5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e1->tag) {
5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return eqIRConst( e1->Iex.Const.con, e2->Iex.Const.con );
5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop:
5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e1->Iex.Binop.op == e2->Iex.Binop.op
5194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && sameIRValue(e1->Iex.Binop.arg1, e2->Iex.Binop.arg1)
5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && sameIRValue(e1->Iex.Binop.arg2, e2->Iex.Binop.arg2);
5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop:
5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e1->Iex.Unop.op == e2->Iex.Unop.op
5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && sameIRValue(e1->Iex.Unop.arg, e2->Iex.Unop.arg);
5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return e1->Iex.RdTmp.tmp == e2->Iex.RdTmp.tmp;
5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X:
5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return sameIRValue( e1->Iex.Mux0X.cond, e2->Iex.Mux0X.cond )
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && sameIRValue( e1->Iex.Mux0X.expr0, e2->Iex.Mux0X.expr0 )
5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && sameIRValue( e1->Iex.Mux0X.exprX, e2->Iex.Mux0X.exprX );
5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop:
5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop:
5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall:
5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* be lazy.  Could define equality for these, but they never
5209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            appear to be used. */
5210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get:
5212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI:
5213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load:
5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* be conservative - these may not give the same value each
5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            time */
5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binder:
5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* should never see this */
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthrough */
5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("mc_translate.c: sameIRValue: unhandled: ");
5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(e1);
5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:sameIRValue");
5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* See if 'pairs' already has an entry for (entry, guard).  Return
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   True if so.  If not, add an entry. */
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool check_or_add ( XArray* /*of Pair*/ pairs, IRExpr* guard, void* entry )
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Pair  p;
5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Pair* pp;
5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   i, n = VG_(sizeXA)( pairs );
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n; i++) {
5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pp = VG_(indexXA)( pairs, i );
5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (pp->entry == entry && sameIRValue(pp->guard, guard))
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p.guard = guard;
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p.entry = entry;
5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(addToXA)( pairs, &p );
5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool is_helperc_value_checkN_fail ( HChar* name )
5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0==VG_(strcmp)(name, "MC_(helperc_value_check0_fail_no_o)")
5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check1_fail_no_o)")
5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check4_fail_no_o)")
5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check8_fail_no_o)")
5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check0_fail_w_o)")
5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check1_fail_w_o)")
5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check4_fail_w_o)")
5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      || 0==VG_(strcmp)(name, "MC_(helperc_value_check8_fail_w_o)");
5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* MC_(final_tidy) ( IRSB* sb_in )
5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*   st;
5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty*  di;
5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*   guard;
5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRCallee* cee;
5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      alreadyPresent;
5269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XArray*   pairs = VG_(newXA)( VG_(malloc), "mc.ft.1",
5270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 VG_(free), sizeof(Pair) );
5271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Scan forwards through the statements.  Each time a call to one
5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of the relevant helpers is seen, check if we have made a
5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      previous call to the same helper using the same guard
5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expression, and if so, delete the call. */
5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < sb_in->stmts_used; i++) {
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sb_in->stmts[i];
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(st);
5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (st->tag != Ist_Dirty)
5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = st->Ist.Dirty.details;
5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guard = di->guard;
5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!guard)
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) { ppIRExpr(guard); VG_(printf)("\n"); }
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cee = di->cee;
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!is_helperc_value_checkN_fail( cee->name ))
5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       /* Ok, we have a call to helperc_value_check0/1/4/8_fail with
5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          guard 'guard'.  Check if we have already seen a call to this
5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          function with the same guard.  If so, delete it.  If not,
5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          add it to the set of calls we do know about. */
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      alreadyPresent = check_or_add( pairs, guard, cee->addr );
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (alreadyPresent) {
5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sb_in->stmts[i] = IRStmt_NoOp();
5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0) VG_(printf)("XX\n");
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(deleteXA)( pairs );
5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sb_in;
5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Origin tracking stuff                                ---*/
5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Almost identical to findShadowTmpV. */
5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp findShadowTmpB ( MCEnv* mce, IRTemp orig )
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TempMapEnt* ent;
5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VG_(indexXA) range-checks 'orig', hence no need to check
5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      here. */
5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ent->kind == Orig);
5315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ent->shadowB == IRTemp_INVALID) {
5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmpB
5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = newTemp( mce, Ity_I32, BSh );
5318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* newTemp may cause mce->tmpMap to resize, hence previous results
5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         from VG_(indexXA) are invalid. */
5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->kind == Orig);
5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(ent->shadowB == IRTemp_INVALID);
5323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ent->shadowB = tmpB;
5324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ent->shadowB;
5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* gen_maxU32 ( MCEnv* mce, IRAtom* b1, IRAtom* b2 )
5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return assignNew( 'B', mce, Ity_I32, binop(Iop_Max32U, b1, b2) );
5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* gen_load_b ( MCEnv* mce, Int szB,
5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRAtom* baseaddr, Int offset )
5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*    hFun;
5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar*   hName;
5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp   bTmp;
5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   aTy   = typeOfIRExpr( mce->sb->tyenv, baseaddr );
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp     opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  ea    = baseaddr;
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (offset != 0) {
5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom* off = aTy == Ity_I32 ? mkU32( offset )
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   : mkU64( (Long)(Int)offset );
5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ea = assignNew( 'B', mce, aTy, binop(opAdd, ea, off));
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bTmp = newTemp(mce, mce->hWordTy, BSh);
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (szB) {
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: hFun  = (void*)&MC_(helperc_b_load1);
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_load1)";
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: hFun  = (void*)&MC_(helperc_b_load2);
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_load2)";
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: hFun  = (void*)&MC_(helperc_b_load4);
5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_load4)";
5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: hFun  = (void*)&MC_(helperc_b_load8);
5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_load8)";
5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 16: hFun  = (void*)&MC_(helperc_b_load16);
5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               hName = "MC_(helperc_b_load16)";
5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("mc_translate.c: gen_load_b: unhandled szB == %d\n", szB);
5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_1_N(
5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bTmp, 1/*regparms*/, hName, VG_(fnptr_to_fnentry)( hFun ),
5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           mkIRExprVec_1( ea )
5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no need to mess with any annotations.  This call accesses
5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      neither guest state nor guest memory. */
5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'B', mce, IRStmt_Dirty(di) );
5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mce->hWordTy == Ity_I64) {
5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64-bit host */
5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp bTmp32 = newTemp(mce, Ity_I32, BSh);
5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'B', mce, bTmp32, unop(Iop_64to32, mkexpr(bTmp)) );
5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mkexpr(bTmp32);
5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32-bit host */
5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mkexpr(bTmp);
5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a shadow store.  guard :: Ity_I1 controls whether the
5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   store really happens; NULL means it unconditionally does. */
5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_store_b ( MCEnv* mce, Int szB,
5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* baseaddr, Int offset, IRAtom* dataB,
5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRAtom* guard )
5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*    hFun;
5395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar*   hName;
5396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
5397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   aTy   = typeOfIRExpr( mce->sb->tyenv, baseaddr );
5398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp     opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom*  ea    = baseaddr;
5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) {
5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isOriginalAtom(mce, guard));
5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(typeOfIRExpr(mce->sb->tyenv, guard) == Ity_I1);
5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (offset != 0) {
5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRAtom* off = aTy == Ity_I32 ? mkU32( offset )
5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   : mkU64( (Long)(Int)offset );
5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ea = assignNew(  'B', mce, aTy, binop(opAdd, ea, off));
5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mce->hWordTy == Ity_I64)
5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dataB = assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, dataB));
5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (szB) {
5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: hFun  = (void*)&MC_(helperc_b_store1);
5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_store1)";
5415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: hFun  = (void*)&MC_(helperc_b_store2);
5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_store2)";
5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: hFun  = (void*)&MC_(helperc_b_store4);
5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_store4)";
5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8: hFun  = (void*)&MC_(helperc_b_store8);
5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              hName = "MC_(helperc_b_store8)";
5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 16: hFun  = (void*)&MC_(helperc_b_store16);
5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               hName = "MC_(helperc_b_store16)";
5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_0_N( 2/*regparms*/,
5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           hName, VG_(fnptr_to_fnentry)( hFun ),
5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           mkIRExprVec_2( ea, dataB )
5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* no need to mess with any annotations.  This call accesses
5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      neither guest state nor guest memory. */
5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) di->guard = guard;
5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( 'B', mce, IRStmt_Dirty(di) );
5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* narrowTo32 ( MCEnv* mce, IRAtom* e ) {
5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType eTy = typeOfIRExpr(mce->sb->tyenv, e);
5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (eTy == Ity_I64)
5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew( 'B', mce, Ity_I32, unop(Iop_64to32, e) );
5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (eTy == Ity_I32)
5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return e;
5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0);
5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* zWidenFrom32 ( MCEnv* mce, IRType dstTy, IRAtom* e ) {
5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType eTy = typeOfIRExpr(mce->sb->tyenv, e);
5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(eTy == Ity_I32);
5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (dstTy == Ity_I64)
5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, e) );
5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(0);
5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* schemeE ( MCEnv* mce, IRExpr* e )
5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(MC_(clo_mc_level) == 3);
5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
5464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_GetI: {
5466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr_b;
5467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom      *t1, *t2, *t3, *t4;
5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr      = e->Iex.GetI.descr;
5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType equivIntTy
5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = MC_(get_otrack_reg_array_equiv_int_type)(descr);
5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If this array is unshadowable for whatever reason, use the
5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            usual approximation. */
5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (equivIntTy == Ity_INVALID)
5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return mkU32(0);
5475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(sizeofIRType(equivIntTy) >= 4);
5476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(sizeofIRType(equivIntTy) == sizeofIRType(descr->elemTy));
5477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         descr_b = mkIRRegArray( descr->base + 2*mce->layout->total_sizeB,
5478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 equivIntTy, descr->nElems );
5479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Do a shadow indexed get of the same size, giving t1.  Take
5480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the bottom 32 bits of it, giving t2.  Compute into t3 the
5481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            origin for the index (almost certainly zero, but there's
5482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            no harm in being completely general here, since iropt will
5483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            remove any useless code), and fold it in, giving a final
5484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            value t4. */
5485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = assignNew( 'B', mce, equivIntTy,
5486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRExpr_GetI( descr_b, e->Iex.GetI.ix,
5487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                e->Iex.GetI.bias ));
5488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t2 = narrowTo32( mce, t1 );
5489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t3 = schemeE( mce, e->Iex.GetI.ix );
5490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t4 = gen_maxU32( mce, t2, t3 );
5491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return t4;
5492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_CCall: {
5494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int i;
5495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom*  here;
5496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr** args = e->Iex.CCall.args;
5497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom*  curr = mkU32(0);
5498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; args[i]; i++) {
5499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(i < 32);
5500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(isOriginalAtom(mce, args[i]));
5501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Only take notice of this arg if the callee's
5502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mc-exclusion mask does not say it is to be excluded. */
5503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (e->Iex.CCall.cee->mcx_mask & (1<<i)) {
5504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* the arg is to be excluded from definedness checking.
5505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Do nothing. */
5506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (0) VG_(printf)("excluding %s(%d)\n",
5507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  e->Iex.CCall.cee->name, i);
5508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
5509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* calculate the arg's definedness, and pessimistically
5510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  merge it in. */
5511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               here = schemeE( mce, args[i] );
5512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               curr = gen_maxU32( mce, curr, here );
5513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return curr;
5516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Load: {
5518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int dszB;
5519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dszB = sizeofIRType(e->Iex.Load.ty);
5520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* assert that the B value for the address is already
5521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            available (somewhere) */
5522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(isIRAtom(e->Iex.Load.addr));
5523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(mce->hWordTy == Ity_I32 || mce->hWordTy == Ity_I64);
5524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return gen_load_b( mce, dszB, e->Iex.Load.addr, 0 );
5525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Mux0X: {
5527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b1 = schemeE( mce, e->Iex.Mux0X.cond );
5528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b2 = schemeE( mce, e->Iex.Mux0X.expr0 );
5529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b3 = schemeE( mce, e->Iex.Mux0X.exprX );
5530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return gen_maxU32( mce, b1, gen_maxU32( mce, b2, b3 ));
5531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Qop: {
5533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b1 = schemeE( mce, e->Iex.Qop.arg1 );
5534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b2 = schemeE( mce, e->Iex.Qop.arg2 );
5535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b3 = schemeE( mce, e->Iex.Qop.arg3 );
5536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b4 = schemeE( mce, e->Iex.Qop.arg4 );
5537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return gen_maxU32( mce, gen_maxU32( mce, b1, b2 ),
5538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 gen_maxU32( mce, b3, b4 ) );
5539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Triop: {
5541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b1 = schemeE( mce, e->Iex.Triop.arg1 );
5542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b2 = schemeE( mce, e->Iex.Triop.arg2 );
5543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b3 = schemeE( mce, e->Iex.Triop.arg3 );
5544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return gen_maxU32( mce, b1, gen_maxU32( mce, b2, b3 ) );
5545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Binop: {
5547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
5548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CasCmpEQ8:  case Iop_CasCmpNE8:
5549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CasCmpEQ16: case Iop_CasCmpNE16:
5550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CasCmpEQ32: case Iop_CasCmpNE32:
5551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CasCmpEQ64: case Iop_CasCmpNE64:
5552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Just say these all produce a defined result,
5553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  regardless of their arguments.  See
5554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  COMMENT_ON_CasCmpEQ in this file. */
5555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return mkU32(0);
5556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: {
5557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRAtom* b1 = schemeE( mce, e->Iex.Binop.arg1 );
5558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRAtom* b2 = schemeE( mce, e->Iex.Binop.arg2 );
5559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return gen_maxU32( mce, b1, b2 );
5560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
5563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*NOTREACHED*/
5564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Unop: {
5566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom* b1 = schemeE( mce, e->Iex.Unop.arg );
5567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return b1;
5568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Const:
5570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkU32(0);
5571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp:
5572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkexpr( findShadowTmpB( mce, e->Iex.RdTmp.tmp ));
5573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_Get: {
5574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int b_offset = MC_(get_otrack_shadow_offset)(
5575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           e->Iex.Get.offset,
5576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           sizeofIRType(e->Iex.Get.ty)
5577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        );
5578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(b_offset >= -1
5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   && b_offset <= mce->layout->total_sizeB -4);
5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b_offset >= 0) {
5581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* FIXME: this isn't an atom! */
5582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return IRExpr_Get( b_offset + 2*mce->layout->total_sizeB,
5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Ity_I32 );
5584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mkU32(0);
5586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("mc_translate.c: schemeE: unhandled: ");
5589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(e);
5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:schemeE");
5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_origins_Dirty ( MCEnv* mce, IRDirty* d )
5596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // This is a hacked version of do_shadow_Dirty
5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int       i, n, toDo, gSz, gOff;
5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom    *here, *curr;
5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp    dst;
5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First check the guard. */
5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   curr = schemeE( mce, d->guard );
5604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now round up all inputs and maxU32 over them. */
5606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: unmasked args */
5608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; d->args[i]; i++) {
5609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->cee->mcx_mask & (1<<i)) {
5610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ignore this arg */
5611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = schemeE( mce, d->args[i] );
5613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = gen_maxU32( mce, curr, here );
5614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: guest state that we read. */
5618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < d->nFxState; i++) {
5619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->fxState[i].fx != Ifx_None);
5620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->fxState[i].fx == Ifx_Write)
5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ignore any sections marked as 'always defined'. */
5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size )) {
5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0)
5626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("memcheck: Dirty gst: ignored off %d, sz %d\n",
5627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     d->fxState[i].offset, d->fxState[i].size );
5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This state element is read or modified.  So we need to
5632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         consider it.  If larger than 4 bytes, deal with it in 4-byte
5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         chunks. */
5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gSz  = d->fxState[i].size;
5635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gOff = d->fxState[i].offset;
5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(gSz > 0);
5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) {
5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int b_offset;
5639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (gSz == 0) break;
5640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n = gSz <= 4 ? gSz : 4;
5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* update 'curr' with maxU32 of the state slice
5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gOff .. gOff+n-1 */
5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_offset = MC_(get_otrack_shadow_offset)(gOff, 4);
5644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b_offset != -1) {
5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            here = assignNew( 'B',mce,
5646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Ity_I32,
5647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               IRExpr_Get(b_offset + 2*mce->layout->total_sizeB,
5648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          Ity_I32));
5649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            curr = gen_maxU32( mce, curr, here );
5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gSz -= n;
5652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gOff += n;
5653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Inputs: memory */
5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx != Ifx_None) {
5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Because we may do multiple shadow loads/stores from the same
5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         base address, it's best to do a single test of its
5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         definedness right now.  Post-instrumentation optimisation
5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         should remove all but this test. */
5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->mAddr);
5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      here = schemeE( mce, d->mAddr );
5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      curr = gen_maxU32( mce, curr, here );
5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with memory inputs (reads or modifies) */
5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toDo   = d->mSize;
5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 32-bit chunks.  We don't care about the endianness
5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         since it's all going to be condensed down to a single bit,
5674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         but nevertheless choose an endianness which is hopefully
5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         native to the platform. */
5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 4) {
5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = gen_load_b( mce, 4, d->mAddr, d->mSize - toDo );
5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = gen_maxU32( mce, curr, here );
5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 4;
5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* handle possible 16-bit excess */
5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 2) {
5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here = gen_load_b( mce, 2, d->mAddr, d->mSize - toDo );
5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         curr = gen_maxU32( mce, curr, here );
5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 2;
5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(toDo == 0); /* also need to handle 1-byte excess */
5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Whew!  So curr is a 32-bit B-value which should give an origin
5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of some use if any of the inputs to the helper are undefined.
5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Now we need to re-distribute the results to all destinations. */
5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: the destination temporary, if there is one. */
5695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->tmp != IRTemp_INVALID) {
5696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst   = findShadowTmpB(mce, d->tmp);
5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( 'V', mce, dst, curr );
5698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: guest state that we write or modify. */
5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < d->nFxState; i++) {
5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(d->fxState[i].fx != Ifx_None);
5703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->fxState[i].fx == Ifx_Read)
5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ignore any sections marked as 'always defined'. */
5707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isAlwaysDefd(mce, d->fxState[i].offset, d->fxState[i].size ))
5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This state element is written or modified.  So we need to
5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         consider it.  If larger than 4 bytes, deal with it in 4-byte
5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         chunks. */
5713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gSz  = d->fxState[i].size;
5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gOff = d->fxState[i].offset;
5715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(gSz > 0);
5716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) {
5717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int b_offset;
5718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (gSz == 0) break;
5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n = gSz <= 4 ? gSz : 4;
5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Write 'curr' to the state slice gOff .. gOff+n-1 */
5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_offset = MC_(get_otrack_shadow_offset)(gOff, 4);
5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b_offset != -1) {
5723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           stmt( 'B', mce, IRStmt_Put(b_offset + 2*mce->layout->total_sizeB,
5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      curr ));
5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gSz -= n;
5727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gOff += n;
5728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Outputs: memory that we write or modify.  Same comments about
5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      endianness as above apply. */
5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      toDo   = d->mSize;
5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* chew off 32-bit chunks */
5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 4) {
5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_store_b( mce, 4, d->mAddr, d->mSize - toDo, curr,
5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      NULL/*guard*/ );
5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 4;
5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* handle possible 16-bit excess */
5742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (toDo >= 2) {
5743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        gen_store_b( mce, 2, d->mAddr, d->mSize - toDo, curr,
5744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     NULL/*guard*/ );
5745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         toDo -= 2;
5746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(toDo == 0); /* also need to handle 1-byte excess */
5748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_origins_Store ( MCEnv* mce,
5753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               IREndness stEnd,
5754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               IRExpr* stAddr,
5755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               IRExpr* stData )
5756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     dszB;
5758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom* dataB;
5759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* assert that the B value for the address is already available
5760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (somewhere), since the call to schemeE will want to see it.
5761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XXXX how does this actually ensure that?? */
5762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(stAddr));
5763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(stData));
5764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dszB  = sizeofIRType( typeOfIRExpr(mce->sb->tyenv, stData ) );
5765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dataB = schemeE( mce, stData );
5766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gen_store_b( mce, dszB, stAddr, 0/*offset*/, dataB,
5767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     NULL/*guard*/ );
5768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void schemeS ( MCEnv* mce, IRStmt* st )
5772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(MC_(clo_mc_level) == 3);
5774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (st->tag) {
5776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_AbiHint:
5778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The value-check instrumenter handles this - by arranging
5779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            to pass the address of the next instruction to
5780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            MC_(helperc_MAKE_STACK_UNINIT).  This is all that needs to
5781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            happen for origin tracking w.r.t. AbiHints.  So there is
5782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nothing to do here. */
5783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_PutI: {
5786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr_b;
5787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRAtom      *t1, *t2, *t3, *t4;
5788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRRegArray* descr = st->Ist.PutI.descr;
5789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType equivIntTy
5790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = MC_(get_otrack_reg_array_equiv_int_type)(descr);
5791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If this array is unshadowable for whatever reason,
5792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            generate no code. */
5793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (equivIntTy == Ity_INVALID)
5794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(sizeofIRType(equivIntTy) >= 4);
5796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(sizeofIRType(equivIntTy) == sizeofIRType(descr->elemTy));
5797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         descr_b
5798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = mkIRRegArray( descr->base + 2*mce->layout->total_sizeB,
5799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            equivIntTy, descr->nElems );
5800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Compute a value to Put - the conjoinment of the origin for
5801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the data to be Put-ted (obviously) and of the index value
5802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (not so obviously). */
5803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t1 = schemeE( mce, st->Ist.PutI.data );
5804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t2 = schemeE( mce, st->Ist.PutI.ix );
5805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t3 = gen_maxU32( mce, t1, t2 );
5806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t4 = zWidenFrom32( mce, equivIntTy, t3 );
5807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( 'B', mce, IRStmt_PutI( descr_b, st->Ist.PutI.ix,
5808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      st->Ist.PutI.bias, t4 ));
5809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Dirty:
5813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_origins_Dirty( mce, st->Ist.Dirty.details );
5814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Store:
5817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_origins_Store( mce, st->Ist.Store.end,
5818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                st->Ist.Store.addr,
5819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                st->Ist.Store.data );
5820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_LLSC: {
5823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* In short: treat a load-linked like a normal load followed
5824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            by an assignment of the loaded (shadow) data the result
5825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            temporary.  Treat a store-conditional like a normal store,
5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            and mark the result temporary as defined. */
5827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (st->Ist.LLSC.storedata == NULL) {
5828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Load Linked */
5829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRType resTy
5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = typeOfIRTemp(mce->sb->tyenv, st->Ist.LLSC.result);
5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* vanillaLoad
5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = IRExpr_Load(st->Ist.LLSC.end, resTy, st->Ist.LLSC.addr);
5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(resTy == Ity_I64 || resTy == Ity_I32
5834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      || resTy == Ity_I16 || resTy == Ity_I8);
5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( 'B', mce, findShadowTmpB(mce, st->Ist.LLSC.result),
5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              schemeE(mce, vanillaLoad));
5837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
5838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Store conditional */
5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            do_origins_Store( mce, st->Ist.LLSC.end,
5840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   st->Ist.LLSC.addr,
5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   st->Ist.LLSC.storedata );
5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* For the rationale behind this, see comments at the
5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               place where the V-shadow for .result is constructed, in
5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               do_shadow_LLSC.  In short, we regard .result as
5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               always-defined. */
5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( 'B', mce, findShadowTmpB(mce, st->Ist.LLSC.result),
5847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(0) );
5848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Put: {
5853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int b_offset
5854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = MC_(get_otrack_shadow_offset)(
5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 st->Ist.Put.offset,
5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 sizeofIRType(typeOfIRExpr(mce->sb->tyenv, st->Ist.Put.data))
5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b_offset >= 0) {
5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* FIXME: this isn't an atom! */
5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( 'B', mce, IRStmt_Put(b_offset + 2*mce->layout->total_sizeB,
5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       schemeE( mce, st->Ist.Put.data )) );
5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_WrTmp:
5867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( 'B', mce, findShadowTmpB(mce, st->Ist.WrTmp.tmp),
5868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           schemeE(mce, st->Ist.WrTmp.data) );
5869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_MBE:
5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_NoOp:
5873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_Exit:
5874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ist_IMark:
5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("mc_translate.c: schemeS: unhandled: ");
5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("memcheck:schemeS");
5881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                           mc_translate.c ---*/
5887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5888