1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                   host_ppc_isel.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2004-2011 OpenWorks LLP
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "ir_match.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_generic_regs.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_ppc_defs.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* GPR register class for ppc32/64 */
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32)
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Register Usage Conventions                        ---*/
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Regs
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ------------
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR0       Reserved
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR1       Stack Pointer
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR2       not used - TOC pointer
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR3:10    Allocateable
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR11      if mode64: not used - calls by ptr / env ptr for some langs
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR12      if mode64: not used - exceptions / global linkage code
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR13      not used - Thread-specific pointer
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR14:28   Allocateable
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR29      Unused by us (reserved for the dispatcher)
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR30      AltiVec temp spill register
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR31      GuestStatePointer
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Of Allocateable regs:
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (mode64)
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GPR3:10  Caller-saved regs
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  else
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GPR3:12  Caller-saved regs
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR14:29   Callee-saved regs
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR3       [Return | Parameter] - carrying reg
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR4:10    Parameter-carrying regs
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Regs
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  -------------------
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FPR0:31    Allocateable
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FPR0       Caller-saved - scratch reg
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (mode64)
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FPR1:13  Caller-saved - param & return regs
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  else
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FPR1:8   Caller-saved - param & return regs
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FPR9:13  Caller-saved regs
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FPR14:31   Callee-saved regs
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Vector Regs (on processors with the VMX feature)
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  -----------
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VR0-VR1    Volatile scratch registers
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VR2-VR13   Volatile vector parameters registers
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VR14-VR19  Volatile scratch registers
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VR20-VR31  Non-volatile registers
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VRSAVE     Non-volatile 32-bit register
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- PPC FP Status & Control Register Conventions      ---*/
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Vex-generated code expects to run with the FPU set as follows: all
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  exceptions masked.  The rounding mode is set appropriately before
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  each floating point insn emitted (or left unchanged if known to be
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  correct already).  There are a few fp insns (fmr,fneg,fabs,fnabs),
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  which are unaffected by the rm and so the rounding mode is not set
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  prior to them.
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  At least on MPC7447A (Mac Mini), frsqrte is also not affected by
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  rounding mode.  At some point the ppc docs get sufficiently vague
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  that the only way to find out is to write test programs.
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notes on the FP instruction set, 6 Feb 06.
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownWhat                 exns -> CR1 ?   Sets FPRF ?   Observes RM ?
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown-------------------------------------------------------------
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmr[.]                   if .             n             n
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfneg[.]                  if .             n             n
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfabs[.]                  if .             n             n
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnabs[.]                 if .             n             n
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfadd[.]                  if .             y             y
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfadds[.]                 if .             y             y
129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovfcfid[.] (Si64->dbl)     if .             y             y
130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovfcfidU[.] (Ui64->dbl)    if .             y             y
131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovfcfids[.] (Si64->sngl)   if .             Y             Y
132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovfcfidus[.] (Ui64->sngl)  if .             Y             Y
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfcmpo (cmp, result       n                n             n
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfcmpu  to crfD)          n                n             n
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfctid[.]  (dbl->i64)     if .       ->undef             y
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfctidz[.] (dbl->i64)     if .       ->undef    rounds-to-zero
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfctiw[.]  (dbl->i32)     if .       ->undef             y
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfctiwz[.] (dbl->i32)     if .       ->undef    rounds-to-zero
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfdiv[.]                  if .             y             y
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfdivs[.]                 if .             y             y
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmadd[.]                 if .             y             y
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmadds[.]                if .             y             y
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmsub[.]                 if .             y             y
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmsubs[.]                if .             y             y
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmul[.]                  if .             y             y
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmuls[.]                 if .             y             y
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown(note: for fnm*, rounding happens before final negation)
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnmadd[.]                if .             y             y
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnmadds[.]               if .             y             y
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnmsub[.]                if .             y             y
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnmsubs[.]               if .             y             y
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfre[.]                   if .             y             y
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfres[.]                  if .             y             y
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfrsqrte[.]               if .             y       apparently not
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfsqrt[.]                 if .             y             y
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfsqrts[.]                if .             y             y
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfsub[.]                  if .             y             y
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfsubs[.]                 if .             y             y
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfpscr: bits 30-31 (ibm) is RM
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            24-29 (ibm) are exnmasks/non-IEEE bit, all zero
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    15-19 (ibm) is FPRF: class, <, =, >, UNord
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownppc fe(guest) makes fpscr read as all zeros except RM (and maybe FPRF
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownin future)
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmcrfs     - move fpscr field to CR field
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmtfsfi[.] - 4 bit imm moved to fpscr field
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmtfsf[.]  - move frS[low 1/2] to fpscr but using 8-bit field mask
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmtfsb1[.] - set given fpscr bit
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmtfsb0[.] - clear given fpscr bit
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmffs[.]   - move all fpscr to frD[low 1/2]
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownFor [.] presumably cr1 is set with exn summary bits, as per
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmain FP insns
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownA single precision store truncates/denormalises the in-register value,
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbut does not round it.  This is so that flds followed by fsts is
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownalways the identity.
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- misc helpers                                      ---*/
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are duplicated in guest-ppc/toIR.c */
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* unop ( IROp op, IRExpr* a )
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Unop(op, a);
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU32 ( UInt i )
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U32(i));
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* bind ( Int binder )
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binder(binder);
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISelEnv                                           ---*/
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This carries around:
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - A mapping from IRTemp to IRType, giving the type of any IRTemp we
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     might encounter.  This is computed before insn selection starts,
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     and does not change.
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - A mapping from IRTemp to HReg.  This tells the insn selector
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     which virtual register(s) are associated with each IRTemp
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      temporary.  This is computed before insn selection starts, and
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      does not change.  We expect this mapping to map precisely the
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      same set of IRTemps as the type mapping does.
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         - vregmap   holds the primary register for the IRTemp.
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         - vregmapHI holds the secondary register for the IRTemp,
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              if any is needed.  That's only for Ity_I64 temps
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              in 32 bit mode or Ity_I128 temps in 64-bit mode.
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - The name of the vreg in which we stash a copy of the link reg,
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      so helper functions don't kill it.
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - The code array, that is, the insns selected so far.
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - A counter, for generating new virtual registers.
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - The host subarchitecture we are selecting insns for.
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This is set at the start and does not change.
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - A Bool to tell us if the host is 32 or 64bit.
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This is set at the start and does not change.
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - An IRExpr*, which may be NULL, holding the IR expression (an
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRRoundingMode-encoded value) to which the FPU's rounding mode
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      was most recently set.  Setting to NULL is always safe.  Used to
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      avoid redundant settings of the FPU's rounding mode, as
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      described in set_FPU_rounding_mode below.
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - A VexMiscInfo*, needed for knowing how to generate
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      function calls for this target
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTypeEnv*   type_env;
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg*        vregmap;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg*        vregmapHI;
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int          n_vregmap;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg         savedLR;
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HInstrArray* code;
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int          vreg_ctr;
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 27 Jan 06: Not currently used, but should be */
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt         hwcaps;
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool         mode64;
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr*      previous_rm;
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VexAbiInfo*  vbi;
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ISelEnv;
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp >= 0);
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp < env->n_vregmap);
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return env->vregmap[tmp];
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void lookupIRTempPair ( HReg* vrHI, HReg* vrLO,
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               ISelEnv* env, IRTemp tmp )
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!env->mode64);
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp >= 0);
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp < env->n_vregmap);
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env->vregmapHI[tmp] != INVALID_HREG);
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vrLO = env->vregmap[tmp];
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vrHI = env->vregmapHI[tmp];
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addInstr ( ISelEnv* env, PPCInstr* instr )
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addHInstr(env->code, instr);
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppPPCInstr(instr, env->mode64);
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegI ( ISelEnv* env )
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcGPR(env->mode64),
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     True/*virtual reg*/);
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegF ( ISelEnv* env )
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegV ( ISelEnv* env )
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Forward declarations                        ---*/
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are organised as iselXXX and iselXXX_wrk pairs.  The
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselXXX_wrk do the real work, but are not to be called directly.
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   checks that all returned registers are virtual.  You should not
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call the _wrk version directly.
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'Word' refers to the size of the native machine word, that is,
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   32-bit int in 32-bit mode and 64-bit int in 64-bit mode.  '2Word'
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   therefore refers to a double-width (64/128-bit) quantity in two
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   integer registers.
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode: compute an I8/I16/I32 into a GPR.
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit mode: compute an I8/I16/I32/I64 into a GPR. */
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e );
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselWordExpr_R     ( ISelEnv* env, IRExpr* e );
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode: Compute an I8/I16/I32 into a RH
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (reg-or-halfword-immediate).
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit mode: Compute an I8/I16/I32/I64 into a RH
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (reg-or-halfword-immediate).
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   It's important to specify whether the immediate is to be regarded
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   as signed or not.  If yes, this will never return -32768 as an
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   immediate; this guaranteed that all signed immediates that are
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return can have their sign inverted if need be.
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH_wrk ( ISelEnv* env,
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Bool syned, IRExpr* e );
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH     ( ISelEnv* env,
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Bool syned, IRExpr* e );
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode: compute an I32 into a RI (reg or 32-bit immediate).
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit mode: compute an I64 into a RI (reg or 64-bit immediate). */
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRI*        iselWordExpr_RI_wrk ( ISelEnv* env, IRExpr* e );
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRI*        iselWordExpr_RI     ( ISelEnv* env, IRExpr* e );
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* In 32 bit mode ONLY, compute an I8 into a
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reg-or-5-bit-unsigned-immediate, the latter being an immediate in
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the range 1 .. 31 inclusive.  Used for doing shift amounts. */
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH5u_wrk ( ISelEnv* env, IRExpr* e );
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH5u     ( ISelEnv* env, IRExpr* e );
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* In 64-bit mode ONLY, compute an I8 into a
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reg-or-6-bit-unsigned-immediate, the latter being an immediate in
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the range 1 .. 63 inclusive.  Used for doing shift amounts. */
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH6u_wrk ( ISelEnv* env, IRExpr* e );
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH6u     ( ISelEnv* env, IRExpr* e );
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode: compute an I32 into an AMode.
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit mode: compute an I64 into an AMode.
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Requires to know (xferTy) the type of data to be loaded/stored
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   using this amode.  That is so that, for 64-bit code generation, any
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode_IR returned will have an index (immediate offset) field
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that is guaranteed to be 4-aligned, if there is any chance that the
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   amode is to be used in ld/ldu/lda/std/stdu.
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Since there are no such restrictions on 32-bit insns, xferTy is
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ignored for 32-bit code generation. */
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCAMode*     iselWordExpr_AMode_wrk ( ISelEnv* env, IRExpr* e, IRType xferTy );
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCAMode*     iselWordExpr_AMode     ( ISelEnv* env, IRExpr* e, IRType xferTy );
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode ONLY: compute an I64 into a GPR pair. */
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void          iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         ISelEnv* env, IRExpr* e );
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void          iselInt64Expr     ( HReg* rHi, HReg* rLo,
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         ISelEnv* env, IRExpr* e );
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void          iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          ISelEnv* env, IRExpr* e );
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void          iselInt128Expr     ( HReg* rHi, HReg* rLo,
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          ISelEnv* env, IRExpr* e );
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCCondCode   iselCondCode_wrk ( ISelEnv* env, IRExpr* e );
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCCondCode   iselCondCode     ( ISelEnv* env, IRExpr* e );
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselDblExpr_wrk ( ISelEnv* env, IRExpr* e );
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselDblExpr     ( ISelEnv* env, IRExpr* e );
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselFltExpr     ( ISelEnv* env, IRExpr* e );
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselVecExpr_wrk ( ISelEnv* env, IRExpr* e );
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselVecExpr     ( ISelEnv* env, IRExpr* e );
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Misc helpers                                ---*/
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make an int reg-reg move. */
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCInstr* mk_iMOVds_RR ( HReg r_dst, HReg r_src )
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_dst) == hregClass(r_src));
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_src) ==  HRcInt32 ||
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           hregClass(r_src) ==  HRcInt64);
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCInstr_Alu(Palu_OR, r_dst, r_src, PPCRH_Reg(r_src));
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Advance/retreat %r1 by n. */
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_to_sp ( ISelEnv* env, UInt n )
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg sp = StackFramePtr(env->mode64);
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n < 256 && (n%16) == 0);
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu( Palu_ADD, sp, sp,
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               PPCRH_Imm(True,toUShort(n)) ));
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sub_from_sp ( ISelEnv* env, UInt n )
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg sp = StackFramePtr(env->mode64);
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n < 256 && (n%16) == 0);
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu( Palu_SUB, sp, sp,
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               PPCRH_Imm(True,toUShort(n)) ));
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  returns a quadword aligned address on the stack
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - copies SP, adds 16bytes, aligns to quadword.
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  use sub_from_sp(32) before calling this,
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  as expects to have 32 bytes to play with.
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg get_sp_aligned16 ( ISelEnv* env )
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg       r = newVRegI(env);
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg align16 = newVRegI(env);
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, mk_iMOVds_RR(r, StackFramePtr(env->mode64)));
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // add 16
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu( Palu_ADD, r, r,
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               PPCRH_Imm(True,toUShort(16)) ));
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // mask to quadword
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env,
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCInstr_LI(align16, 0xFFFFFFFFFFFFFFF0ULL, env->mode64));
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu(Palu_AND, r,r, PPCRH_Reg(align16)));
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Load 2*I32 regs to fp reg */
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg mk_LoadRR32toFPR ( ISelEnv* env,
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               HReg r_srcHi, HReg r_srcLo )
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg fr_dst = newVRegF(env);
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode *am_addr0, *am_addr1;
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!env->mode64);
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_srcHi) == HRcInt32);
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_srcLo) == HRcInt32);
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sub_from_sp( env, 16 );        // Move SP down 16 bytes
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am_addr1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // store hi,lo as Ity_I32's
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Store( 4, am_addr0, r_srcHi, env->mode64 ));
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Store( 4, am_addr1, r_srcLo, env->mode64 ));
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // load as float
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_sp( env, 16 );          // Reset SP
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return fr_dst;
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Load I64 reg to fp reg */
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg mk_LoadR64toFPR ( ISelEnv* env, HReg r_src )
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg fr_dst = newVRegF(env);
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode *am_addr0;
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env->mode64);
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_src) == HRcInt64);
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sub_from_sp( env, 16 );        // Move SP down 16 bytes
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // store as Ity_I64
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Store( 8, am_addr0, r_src, env->mode64 ));
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // load as float
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_sp( env, 16 );          // Reset SP
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return fr_dst;
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given an amode, return one which references 4 bytes further
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along. */
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCAMode* advance4 ( ISelEnv* env, PPCAMode* am )
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode* am4 = dopyPPCAMode( am );
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (am4->tag == Pam_IR
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && am4->Pam.IR.index + 4 <= 32767) {
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am4->Pam.IR.index += 4;
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("advance4(ppc,host)");
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am4;
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given a guest-state array descriptor, an index expression and a
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias, generate a PPCAMode pointing at the relevant piece of
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest state.  */
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPPCAMode* genGuestArrayOffset ( ISelEnv* env, IRRegArray* descr,
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr* off, Int bias )
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg rtmp, roff;
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  elemSz = sizeofIRType(descr->elemTy);
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  nElems = descr->nElems;
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  shift  = 0;
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Throw out any cases we don't need.  In theory there might be a
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      day where we need to handle others, but not today. */
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (nElems != 16 && nElems != 32)
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("genGuestArrayOffset(ppc host)(1)");
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (elemSz) {
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  shift = 2; break;
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  shift = 3; break;
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("genGuestArrayOffset(ppc host)(2)");
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bias < -100 || bias > 100) /* somewhat arbitrarily */
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("genGuestArrayOffset(ppc host)(3)");
565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (descr->base < 0 || descr->base > 5000) /* somewhat arbitrarily */
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("genGuestArrayOffset(ppc host)(4)");
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Compute off into a reg, %off.  Then return:
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addi %tmp, %off, bias (if bias != 0)
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         andi %tmp, nElems-1
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sldi %tmp, shift
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addi %tmp, %tmp, base
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ... Baseblockptr + %tmp ...
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   roff = iselWordExpr_R(env, off);
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rtmp = newVRegI(env);
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu(
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Palu_ADD,
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rtmp, roff,
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PPCRH_Imm(True/*signed*/, toUShort(bias))));
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu(
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Palu_AND,
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rtmp, rtmp,
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PPCRH_Imm(False/*unsigned*/, toUShort(nElems-1))));
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Shft(
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Pshft_SHL,
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    env->mode64 ? False : True/*F:64-bit, T:32-bit shift*/,
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rtmp, rtmp,
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PPCRH_Imm(False/*unsigned*/, toUShort(shift))));
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu(
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Palu_ADD,
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rtmp, rtmp,
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PPCRH_Imm(True/*signed*/, toUShort(descr->base))));
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode_RR( GuestStatePtr(env->mode64), rtmp );
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Function call helpers                       ---*/
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Used only in doHelperCall.  See big comment in doHelperCall re
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   handling of register-parameter args.  This function figures out
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   whether evaluation of an expression might require use of a fixed
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register.  If in doubt return True (safe but suboptimal).
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool mightRequireFixedRegs ( IRExpr* e )
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_RdTmp: case Iex_Const: case Iex_Get:
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a complete function call.  guard is a Ity_Bit expression
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   indicating whether or not the call happens.  If guard==NULL, the
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call is unconditional. */
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid doHelperCall ( ISelEnv* env,
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Bool passBBP,
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    IRExpr* guard, IRCallee* cee, IRExpr** args )
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCCondCode cc;
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg        argregs[PPC_N_REGPARMS];
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg        tmpregs[PPC_N_REGPARMS];
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool        go_fast;
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int         n_args, i, argreg;
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt        argiregs;
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong       target;
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool        mode64 = env->mode64;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Do we need to force use of an odd-even reg pair for 64-bit
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      args? */
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool regalign_int64s
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = (!mode64) && env->vbi->host_ppc32_regalign_int64_args;
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Marshal args for a call and do the call.
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If passBBP is True, %rbp (the baseblock pointer) is to be passed
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      as the first arg.
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This function only deals with a tiny set of possibilities, which
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cover all helpers in practice.  The restrictions are that only
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arguments in registers are supported, hence only PPC_N_REGPARMS x
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (mode32:32 | mode64:64) integer bits in total can be passed.
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      In fact the only supported arg type is (mode32:I32 | mode64:I64).
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Generating code which is both efficient and correct when
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      parameters are to be passed in registers is difficult, for the
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reasons elaborated in detail in comments attached to
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall() in priv/host-x86/isel.c.  Here, we use a variant
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of the method described in those comments.
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The problem is split into two cases: the fast scheme and the
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      slow scheme.  In the fast scheme, arguments are computed
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      directly into the target (real) registers.  This is only safe
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      when we can be sure that computation of each argument will not
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      trash any real registers set by computation of any other
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argument.
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      In the slow scheme, all args are first computed into vregs, and
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      once they are all done, they are moved to the relevant real
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      regs.  This always gives correct code, but it also gives a bunch
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of vreg-to-rreg moves which are usually redundant but are hard
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for the register allocator to get rid of.
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      To decide which scheme to use, all argument expressions are
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      first examined.  If they are all so simple that it is clear they
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      will be evaluated without use of any fixed registers, use the
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fast scheme, else use the slow scheme.  Note also that only
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unconditional calls may use the fast scheme, since having to
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      compute a condition expression could itself trash real
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      registers.
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Note this requires being able to examine an expression and
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      determine whether or not evaluation of it might use a fixed
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register.  That requires knowledge of how the rest of this insn
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      selector works.  Currently just the following 3 are regarded as
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      safe -- hopefully they cover the majority of arguments in
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note that the cee->regparms field is meaningless on PPC32/64 host
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (since there is only one calling convention) and so we always
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ignore it. */
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_args = 0;
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; args[i]; i++)
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_args++;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (PPC_N_REGPARMS < n_args + (passBBP ? 1 : 0)) {
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("doHelperCall(PPC): cannot currently handle > 8 args");
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // PPC_N_REGPARMS
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[0] = hregPPC_GPR3(mode64);
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[1] = hregPPC_GPR4(mode64);
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[2] = hregPPC_GPR5(mode64);
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[3] = hregPPC_GPR6(mode64);
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[4] = hregPPC_GPR7(mode64);
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[5] = hregPPC_GPR8(mode64);
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[6] = hregPPC_GPR9(mode64);
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[7] = hregPPC_GPR10(mode64);
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argiregs = 0;
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmpregs[0] = tmpregs[1] = tmpregs[2] =
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmpregs[3] = tmpregs[4] = tmpregs[5] =
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmpregs[6] = tmpregs[7] = INVALID_HREG;
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First decide which scheme (slow or fast) is to be used.  First
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assume the fast scheme, and select slow if any contraindications
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (wow) appear. */
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   go_fast = True;
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) {
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard->tag == Iex_Const
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->tag == Ico_U1
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->Ico.U1 == True) {
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unconditional */
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Not manifestly unconditional -- be conservative. */
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         go_fast = False;
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (go_fast) {
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < n_args; i++) {
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mightRequireFixedRegs(args[i])) {
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            go_fast = False;
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* At this point the scheme to use has been established.  Generate
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      code to get the arg values into the argument rregs. */
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (go_fast) {
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FAST SCHEME */
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argreg = 0;
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (passBBP) {
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argiregs |= (1 << (argreg+3));
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR( argregs[argreg],
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     GuestStatePtr(mode64) ));
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argreg++;
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < n_args; i++) {
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(argreg < PPC_N_REGPARMS);
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32 ||
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) {
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argiregs |= (1 << (argreg+3));
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env,
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mk_iMOVds_RR( argregs[argreg],
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      iselWordExpr_R(env, args[i]) ));
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else { // Ity_I64
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg rHi, rLo;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (regalign_int64s && (argreg%2) == 1)
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              // ppc32 ELF abi spec for passing LONG_LONG
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  argreg++;   // XXX: odd argreg => even rN
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(argreg < PPC_N_REGPARMS-1);
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               iselInt64Expr(&rHi,&rLo, env, args[i]);
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argiregs |= (1 << (argreg+3));
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argiregs |= (1 << (argreg+3));
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else { // mode64
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argiregs |= (1 << (argreg+3));
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVds_RR( argregs[argreg],
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        iselWordExpr_R(env, args[i]) ));
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argreg++;
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fast scheme only applies for unconditional calls.  Hence: */
788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SLOW SCHEME; move via temporaries */
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argreg = 0;
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (passBBP) {
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is pretty stupid; better to move directly to r3
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            after the rest of the args are done. */
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmpregs[argreg] = newVRegI(env);
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR( tmpregs[argreg],
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     GuestStatePtr(mode64) ));
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argreg++;
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < n_args; i++) {
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(argreg < PPC_N_REGPARMS);
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32 ||
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) {
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmpregs[argreg] = iselWordExpr_R(env, args[i]);
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else { // Ity_I64
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg rHi, rLo;
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (regalign_int64s && (argreg%2) == 1)
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             // ppc32 ELF abi spec for passing LONG_LONG
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  argreg++;  // XXX: odd argreg => even rN
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(argreg < PPC_N_REGPARMS-1);
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               iselInt64Expr(&rHi,&rLo, env, args[i]);
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmpregs[argreg++] = rHi;
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmpregs[argreg]   = rLo;
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else { // mode64
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmpregs[argreg] = iselWordExpr_R(env, args[i]);
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argreg++;
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now we can compute the condition.  We can't do it earlier
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         because the argument computations could trash the condition
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         codes.  Be a bit clever to handle the common case where the
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         guard is 1:Bit. */
831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard) {
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (guard->tag == Iex_Const
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && guard->Iex.Const.con->tag == Ico_U1
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && guard->Iex.Const.con->Ico.U1 == True) {
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* unconditional -- do nothing */
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cc = iselCondCode( env, guard );
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Move the args to their final destinations. */
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < argreg; i++) {
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tmpregs[i] == INVALID_HREG)  // Skip invalid regs
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* None of these insns, including any spill code that might
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            be generated, may alter the condition codes. */
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argiregs |= (1 << (i+3));
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) );
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   target = mode64 ? Ptr_to_ULong(cee->addr) :
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     toUInt(Ptr_to_ULong(cee->addr));
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, the call itself. */
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs ));
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: FP rounding mode helpers                    ---*/
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown///* Set FPU's rounding mode to the default */
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//static
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//void set_FPU_rounding_default ( ISelEnv* env )
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//{
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   HReg fr_src = newVRegF(env);
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   HReg r_src  = newVRegI(env);
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   /* Default rounding mode = 0x0
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      Only supporting the rounding-mode bits - the rest of FPSCR is 0x0
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//       - so we can set the whole register at once (faster)
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      note: upper 32 bits ignored by FpLdFPSCR
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   */
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   addInstr(env, PPCInstr_LI(r_src, 0x0, env->mode64));
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (env->mode64) {
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fr_src = mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   } else {
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fr_src = mk_LoadRR32toFPR( env, r_src, r_src ); // 2*I32 -> F64
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   addInstr(env, PPCInstr_FpLdFPSCR( fr_src ));
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//}
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Convert IR rounding mode to PPC encoding */
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg roundModeIRtoPPC ( ISelEnv* env, HReg r_rmIR )
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rounding mode | PPC | IR
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to nearest    | 00  | 00
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to zero       | 01  | 11
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to +infinity  | 10  | 10
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to -infinity  | 11  | 01
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r_rmPPC = newVRegI(env);
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r_tmp1  = newVRegI(env);
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_rmIR) == HRcGPR(env->mode64));
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // r_rmPPC = XOR(r_rmIR, r_rmIR << 1) & 3
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // slwi  tmp1,    r_rmIR, 1
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // xor   tmp1,    r_rmIR, tmp1
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // andi  r_rmPPC, tmp1, 3
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               r_tmp1, r_rmIR, PPCRH_Imm(False,1)));
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu( Palu_XOR, r_tmp1, r_rmIR,
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               PPCRH_Reg(r_tmp1) ));
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu( Palu_AND, r_rmPPC, r_tmp1,
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               PPCRH_Imm(False,3) ));
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r_rmPPC;
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the FPU's rounding mode: 'mode' is an I32-typed expression
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   denoting a value in the range 0 .. 3, indicating a round mode
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   encoded as per type IRRoundingMode.  Set the PPC FPSCR to have the
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   same rounding.
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For speed & simplicity, we're setting the *entire* FPSCR here.
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Setting the rounding mode is expensive.  So this function tries to
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   avoid repeatedly setting the rounding mode to the same thing by
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   first comparing 'mode' to the 'mode' tree supplied in the previous
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call to this function, if any.  (The previous value is stored in
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->previous_rm.)  If 'mode' is a single IR temporary 't' and
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->previous_rm is also just 't', then the setting is skipped.
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is safe because of the SSA property of IR: an IR temporary can
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   only be defined once and so will have the same value regardless of
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   where it appears in the block.  Cool stuff, SSA.
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A safety condition: all attempts to set the RM must be aware of
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this mechanism - by being routed through the functions here.
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Of course this only helps if blocks where the RM is set more than
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   once and it is set to the same value each time, *and* that value is
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   held in the same IR temporary each time.  In order to assure the
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   latter as much as possible, the IR optimiser takes care to do CSE
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   on any block with any sign of floating point activity.
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg fr_src = newVRegF(env);
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r_src;
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,mode) == Ity_I32);
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Do we need to do anything? */
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (env->previous_rm
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && env->previous_rm->tag == Iex_RdTmp
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && mode->tag == Iex_RdTmp
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && env->previous_rm->Iex.RdTmp.tmp == mode->Iex.RdTmp.tmp) {
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no - setting it to what it was before.  */
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(typeOfIRExpr(env->type_env, env->previous_rm) == Ity_I32);
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* No luck - we better set it, and remember what we set it to. */
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->previous_rm = mode;
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Only supporting the rounding-mode bits - the rest of FPSCR is
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0x0 - so we can set the whole register at once (faster). */
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Resolve rounding mode and convert to PPC representation
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r_src = roundModeIRtoPPC( env, iselWordExpr_R(env, mode) );
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // gpr -> fpr
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (env->mode64) {
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fr_src = mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fr_src = mk_LoadRR32toFPR( env, r_src, r_src ); // 2*I32 -> F64
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Move to FPSCR
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_FpLdFPSCR( fr_src ));
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: vector helpers                              ---*/
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate all-zeroes into a new vector register.
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg generate_zeroes_V128 ( ISelEnv* env )
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg dst = newVRegV(env);
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBinary(Pav_XOR, dst, dst, dst));
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dst;
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1000f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* Generate all-ones into a new vector register.
1001f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root*/
1002f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootstatic HReg generate_ones_V128 ( ISelEnv* env )
1003f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
1004f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   HReg dst = newVRegV(env);
1005f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   PPCVI5s * src = PPCVI5s_Imm(-1);
1006f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   addInstr(env, PPCInstr_AvSplat(8, dst, src));
1007f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   return dst;
1008f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
1009f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Generates code for AvSplat
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  - takes in IRExpr* of type 8|16|32
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    returns vector reg of duplicated lanes of input
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  - uses AvSplat(imm) for imms up to simm6.
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    otherwise must use store reg & load vector
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg mk_AvDuplicateRI( ISelEnv* env, IRExpr* e )
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg   r_src;
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg   dst = newVRegV(env);
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRI* ri  = iselWordExpr_RI(env, e);
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty  = typeOfIRExpr(env->type_env,e);
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   sz  = (ty == Ity_I8) ? 8 : (ty == Ity_I16) ? 16 : 32;
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ri->tag == Pri_Imm) {
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int simm32 = (Int)ri->Pri.Imm;
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* figure out if it's do-able with imm splats. */
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (simm32 >= -32 && simm32 <= 31) {
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Char simm6 = (Char)simm32;
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (simm6 > 15) {           /* 16:31 inclusive */
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg v1 = newVRegV(env);
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg v2 = newVRegV(env);
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvSplat(sz, v1, PPCVI5s_Imm(-16)));
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvSplat(sz, v2, PPCVI5s_Imm(simm6-16)));
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sz== 8) ? PPCInstr_AvBin8x16(Pav_SUBU, dst, v2, v1) :
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sz==16) ? PPCInstr_AvBin16x8(Pav_SUBU, dst, v2, v1)
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        : PPCInstr_AvBin32x4(Pav_SUBU, dst, v2, v1) );
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (simm6 < -16) {          /* -32:-17 inclusive */
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg v1 = newVRegV(env);
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg v2 = newVRegV(env);
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvSplat(sz, v1, PPCVI5s_Imm(-16)));
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvSplat(sz, v2, PPCVI5s_Imm(simm6+16)));
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sz== 8) ? PPCInstr_AvBin8x16(Pav_ADDU, dst, v2, v1) :
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sz==16) ? PPCInstr_AvBin16x8(Pav_ADDU, dst, v2, v1)
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        : PPCInstr_AvBin32x4(Pav_ADDU, dst, v2, v1) );
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* simplest form:              -16:15 inclusive */
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvSplat(sz, dst, PPCVI5s_Imm(simm6)));
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no luck; use the Slow way. */
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r_src = newVRegI(env);
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(r_src, (Long)simm32, env->mode64));
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r_src = ri->Pri.Reg;
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: store r_src in lowest lane of 16-aligned mem,
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      load vector, splat lowest lane to dst */
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CAB: Maybe faster to store r_src multiple times (sz dependent),
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              and simply load the vector? */
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_aligned16;
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg v_src = newVRegV(env);
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode *am_off12;
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sub_from_sp( env, 32 );     // Move SP down
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Get a 16-aligned address within our stack space */
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r_aligned16 = get_sp_aligned16( env );
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_off12 = PPCAMode_IR( 12, r_aligned16 );
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Store r_src in low word of 16-aligned mem */
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Store( 4, am_off12, r_src, env->mode64 ));
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Load src to vector[low lane] */
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, v_src, am_off12 ) );
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_sp( env, 32 );       // Reset SP
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Finally, splat v_src[low_lane] to dst */
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_AvSplat(sz, dst, PPCVI5s_Reg(v_src)));
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* for each lane of vSrc: lane == nan ? laneX = all 1's : all 0's */
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg isNan ( ISelEnv* env, HReg vSrc )
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg zeros, msk_exp, msk_mnt, expt, mnts, vIsNan;
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(vSrc) == HRcVec128);
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   zeros   = mk_AvDuplicateRI(env, mkU32(0));
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   msk_exp = mk_AvDuplicateRI(env, mkU32(0x7F800000));
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   msk_mnt = mk_AvDuplicateRI(env, mkU32(0x7FFFFF));
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expt    = newVRegV(env);
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mnts    = newVRegV(env);
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vIsNan  = newVRegV(env);
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32bit float => sign(1) | exponent(8) | mantissa(23)
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nan => exponent all ones, mantissa > 0 */
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBinary(Pav_AND, expt, vSrc, msk_exp));
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, expt, expt, msk_exp));
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBinary(Pav_AND, mnts, vSrc, msk_mnt));
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBin32x4(Pav_CMPGTU, mnts, mnts, zeros));
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBinary(Pav_AND, vIsNan, expt, mnts));
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return vIsNan;
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select insns for an integer-typed expression, and add them to the
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code list.  Return a reg holding the result.  This reg will be a
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   want to modify it, ask for a new vreg, copy it in there, and modify
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the copy.  The register allocator will do its best to map both
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vregs to the same real register, so the copies will often disappear
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   later in the game.
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This should handle expressions of 64, 32, 16 and 8-bit type.
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   All results are returned in a (mode64 ? 64bit : 32bit) register.
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are arbitrary, so you should mask or sign extend partial values
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if necessary.
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselWordExpr_R ( ISelEnv* env, IRExpr* e )
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselWordExpr_R_wrk(env, e);
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcGPR(env->mode64));
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e )
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MatchInfo mi;
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DECLARE_PATTERN(p_32to1_then_1Uto8);
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8 || ty == Ity_I16 ||
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ty == Ity_I32 || ((ty == Ity_I64) && mode64));
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TEMP --------- */
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_RdTmp:
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LOAD --------- */
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Load: {
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      r_dst;
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr;
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Load.end != Iend_BE)
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto irreducible;
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r_dst   = newVRegI(env);
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_addr = iselWordExpr_AMode( env, e->Iex.Load.addr, ty/*of xfer*/ );
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   r_dst, am_addr, mode64 ));
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY OP --------- */
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Binop: {
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAluOp  aluOp;
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCShftOp shftOp;
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Is it an addition or logical style op? */
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8: case Iop_Add16: case Iop_Add32: case Iop_Add64:
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_ADD; break;
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: case Iop_Sub64:
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_SUB; break;
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And8: case Iop_And16: case Iop_And32: case Iop_And64:
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_AND; break;
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or8:  case Iop_Or16:  case Iop_Or32:  case Iop_Or64:
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_OR; break;
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: case Iop_Xor64:
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_XOR; break;
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_INVALID; break;
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* For commutative ops we assume any literal
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         values are on the second operand. */
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (aluOp != Palu_INVALID) {
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst   = newVRegI(env);
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRH* ri_srcR = NULL;
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get right arg into an RH, in the appropriate way */
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (aluOp) {
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Palu_ADD: case Palu_SUB:
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ri_srcR = iselWordExpr_RH(env, True/*signed*/,
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      e->Iex.Binop.arg2);
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Palu_AND: case Palu_OR: case Palu_XOR:
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ri_srcR = iselWordExpr_RH(env, False/*signed*/,
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      e->Iex.Binop.arg2);
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("iselWordExpr_R_wrk-aluOp-arg2");
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* a shift? */
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl8: case Iop_Shl16: case Iop_Shl32: case Iop_Shl64:
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shftOp = Pshft_SHL; break;
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr8: case Iop_Shr16: case Iop_Shr32: case Iop_Shr64:
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shftOp = Pshft_SHR; break;
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar8: case Iop_Sar16: case Iop_Sar32: case Iop_Sar64:
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shftOp = Pshft_SAR; break;
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shftOp = Pshft_INVALID; break;
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* we assume any literal values are on the second operand. */
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shftOp != Pshft_INVALID) {
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst   = newVRegI(env);
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRH* ri_srcR = NULL;
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get right arg into an RH, in the appropriate way */
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (shftOp) {
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Pshft_SHL: case Pshft_SHR: case Pshft_SAR:
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!mode64)
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2);
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("iselIntExpr_R_wrk-shftOp-arg2");
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* widen the left arg if needed */
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (shftOp == Pshft_SHR || shftOp == Pshft_SAR) {
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ty == Ity_I8 || ty == Ity_I16) {
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               PPCRH* amt = PPCRH_Imm(False,
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      toUShort(ty == Ity_I8 ? 24 : 16));
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg   tmp = newVRegI(env);
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, PPCInstr_Shft(Pshft_SHL,
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           True/*32bit shift*/,
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           tmp, r_srcL, amt));
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, PPCInstr_Shft(shftOp,
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           True/*32bit shift*/,
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           tmp, tmp,    amt));
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_srcL = tmp;
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0); /* AWAITING TEST CASE */
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Only 64 expressions need 64bit shifts,
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            32bit shifts are fine for all others */
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ty == Ity_I64) {
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(mode64);
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(shftOp, False/*64bit shift*/,
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        r_dst, r_srcL, ri_srcR));
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(shftOp, True/*32bit shift*/,
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        r_dst, r_srcL, ri_srcR));
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* How about a div? */
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_DivS32 ||
1287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          e->Iex.Binop.op == Iop_DivU32 ||
1288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          e->Iex.Binop.op == Iop_DivS32E ||
1289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          e->Iex.Binop.op == Iop_DivU32E) {
1290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS32) || (e->Iex.Binop.op == Iop_DivS32E));
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegI(env);
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr( env,
1295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivU32E )
1296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             || ( e->Iex.Binop.op == Iop_DivS32E ) ) ? True
1297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                                                     : False,
1298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    syned,
1299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    True/*32bit div*/,
1300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_dst,
1301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_srcL,
1302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_srcR ) );
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_DivS64 ||
1306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          e->Iex.Binop.op == Iop_DivU64 || e->Iex.Binop.op == Iop_DivS64E
1307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          || e->Iex.Binop.op == Iop_DivU64E ) {
1308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS64) ||(e->Iex.Binop.op == Iop_DivS64E));
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegI(env);
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr( env,
1314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivS64E )
1315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             || ( e->Iex.Binop.op
1316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                      == Iop_DivU64E ) ) ? True
1317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                                         : False,
1318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    syned,
1319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    False/*64bit div*/,
1320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_dst,
1321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_srcL,
1322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_srcR ) );
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* No? Anyone for a mul? */
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_Mul32
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_Mul64) {
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool syned       = False;
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool sz32        = (e->Iex.Binop.op != Iop_Mul64);
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst       = newVRegI(env);
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcL      = iselWordExpr_R(env, e->Iex.Binop.arg1);
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcR      = iselWordExpr_R(env, e->Iex.Binop.arg2);
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(syned, False/*lo32*/, sz32,
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, r_srcL, r_srcR));
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32 x 32 -> 64 multiply */
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && (e->Iex.Binop.op == Iop_MullU32
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || e->Iex.Binop.op == Iop_MullS32)) {
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tLo    = newVRegI(env);
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi    = newVRegI(env);
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegI(env);
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool syned  = toBool(e->Iex.Binop.op == Iop_MullS32);
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     False/*lo32*/, True/*32bit mul*/,
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tLo, r_srcL, r_srcR));
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(syned,
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     True/*hi32*/, True/*32bit mul*/,
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tHi, r_srcL, r_srcR));
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, tHi, PPCRH_Imm(False,32)));
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR,
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_dst, r_dst, PPCRH_Reg(tLo)));
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* El-mutanto 3-way compare? */
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_CmpORD32S
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_CmpORD32U) {
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD32S);
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   dst   = newVRegI(env);
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, srcL, srcR));
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MfCR(dst));
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    PPCRH_Imm(False,7<<1)));
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_CmpORD64S
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_CmpORD64U) {
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD64S);
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   dst   = newVRegI(env);
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, srcL, srcR));
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MfCR(dst));
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    PPCRH_Imm(False,7<<1)));
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_Max32U) {
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        r1   = iselWordExpr_R(env, e->Iex.Binop.arg1);
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        r2   = iselWordExpr_R(env, e->Iex.Binop.arg2);
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        rdst = newVRegI(env);
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cc   = mk_PPCCondCode( Pct_TRUE, Pcf_7LT );
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(rdst, r1));
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, rdst, PPCRH_Reg(r2)));
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_CMov(cc, rdst, PPCRI_Reg(r2)));
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rdst;
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_32HLto64) {
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_Hi  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_Lo  = iselWordExpr_R(env, e->Iex.Binop.arg2);
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   msk   = newVRegI(env);
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* r_dst = OR( r_Hi<<32, r_Lo ) */
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, r_Hi, PPCRH_Imm(False,32)));
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(msk, 0xFFFFFFFF, mode64));
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu( Palu_AND, r_Lo, r_Lo,
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Reg(msk) ));
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu( Palu_OR, r_dst, r_dst,
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Reg(r_Lo) ));
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_CmpF64) {
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_srcL    = iselDblExpr(env, e->Iex.Binop.arg1);
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_srcR    = iselDblExpr(env, e->Iex.Binop.arg2);
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccPPC   = newVRegI(env);
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccIR    = newVRegI(env);
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccIR_b0 = newVRegI(env);
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccIR_b2 = newVRegI(env);
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccIR_b6 = newVRegI(env);
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpCmp(r_ccPPC, fr_srcL, fr_srcR));
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Map compare result from PPC to IR,
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            conforming to CmpF64 definition. */
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           FP cmp result | PPC | IR
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           --------------------------
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           UN            | 0x1 | 0x45
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           EQ            | 0x2 | 0x40
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           GT            | 0x4 | 0x00
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           LT            | 0x8 | 0x01
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // r_ccIR_b0 = r_ccPPC[0] | r_ccPPC[3]
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_ccIR_b0, r_ccPPC,
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Imm(False,0x3)));
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b0,
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccPPC,   PPCRH_Reg(r_ccIR_b0)));
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b0,
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR_b0, PPCRH_Imm(False,0x1)));
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // r_ccIR_b2 = r_ccPPC[0]
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_ccIR_b2, r_ccPPC,
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Imm(False,0x2)));
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b2,
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR_b2, PPCRH_Imm(False,0x4)));
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // r_ccIR_b6 = r_ccPPC[0] | r_ccPPC[1]
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_ccIR_b6, r_ccPPC,
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Imm(False,0x1)));
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b6,
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccPPC, PPCRH_Reg(r_ccIR_b6)));
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_ccIR_b6, r_ccIR_b6,
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Imm(False,0x6)));
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b6,
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR_b6, PPCRH_Imm(False,0x40)));
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR_b0, PPCRH_Reg(r_ccIR_b2)));
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR,    PPCRH_Reg(r_ccIR_b6)));
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_ccIR;
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if ( e->Iex.Binop.op == Iop_F64toI32S ||
1481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e->Iex.Binop.op == Iop_F64toI32U ) {
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This works in both mode64 and mode32. */
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      r1      = StackFramePtr(env->mode64);
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2);
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      ftmp    = newVRegF(env);
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      idst    = newVRegI(env);
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Set host rounding mode */
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 16 );
1493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/,
1494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       e->Iex.Binop.op == Iop_F64toI32S ? True/*syned*/
1495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                                     : False,
1496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       True/*flt64*/,
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       ftmp, fsrc));
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpSTFIW(r1, ftmp));
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load(4, idst, zero_r1, mode64));
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* in 64-bit mode we need to sign-widen idst. */
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64)
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Unary(Pun_EXTSW, idst, idst));
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 16 );
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ///* Restore default FPU rounding. */
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         //set_FPU_rounding_default( env );
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return idst;
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (e->Iex.Binop.op == Iop_F64toI64S || e->Iex.Binop.op == Iop_F64toI64U ) {
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      r1      = StackFramePtr(env->mode64);
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2);
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      idst    = newVRegI(env);
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      ftmp    = newVRegF(env);
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Set host rounding mode */
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          ( e->Iex.Binop.op == Iop_F64toI64S ) ? True
1526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                                            : False,
1527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          True, ftmp, fsrc));
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ///* Restore default FPU rounding. */
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //set_FPU_rounding_default( env );
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return idst;
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- UNARY OP --------- */
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Unop: {
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp op_unop = e->Iex.Unop.op;
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 1Uto8(32to1(expr32)) */
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DEFINE_PATTERN(p_32to1_then_1Uto8,
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* expr32 = mi.bindee[0];
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, expr32);
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_dst,
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_src, PPCRH_Imm(False,1)));
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 16Uto32(LDbe:I16(expr32)) */
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DECLARE_PATTERN(p_LDbe16_then_16Uto32);
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN(p_LDbe16_then_16Uto32,
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_16Uto32,
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Load(Iend_BE,Ity_I16,bind(0))) );
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi,p_LDbe16_then_16Uto32,e)) {
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg r_dst = newVRegI(env);
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* amode
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = iselWordExpr_AMode( env, mi.bindee[0], Ity_I16/*xfer*/ );
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load(2,r_dst,amode, mode64));
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r_dst;
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (op_unop) {
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto16:
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto32:
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto64:
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Uto32:
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Uto64: {
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UShort mask  = toUShort(op_unop==Iop_16Uto64 ? 0xFFFF :
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 op_unop==Iop_16Uto32 ? 0xFFFF : 0xFF);
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND,r_dst,r_src,
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    PPCRH_Imm(False,mask)));
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Uto64: {
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,32)));
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,32)));
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto16:
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto32:
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Sto32: {
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UShort amt   = toUShort(op_unop==Iop_16Sto32 ? 16 : 24);
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,amt)));
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,amt)));
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto64:
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Sto64: {
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UShort amt   = toUShort(op_unop==Iop_8Sto64  ? 56 : 48);
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,amt)));
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,amt)));
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Sto64: {
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 vassert(mode64);
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* According to the IBM docs, in 64 bit mode, srawi r,r,0
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sign extends the lower 32 bits into the upper 32 bits. */
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,0)));
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not8:
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not16:
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not32:
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not64: {
1641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (op_unop == Iop_Not64) vassert(mode64);
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NOT,r_dst,r_src));
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HIto32: {
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) {
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rHi; /* and abandon rLo .. poor wee thing :-) */
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg   r_dst = newVRegI(env);
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   r_dst, r_src, PPCRH_Imm(False,32)));
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r_dst;
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to32: {
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) {
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rLo; /* similar stupid comment to the above ... */
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This is a no-op. */
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return iselWordExpr_R(env, e->Iex.Unop.arg);
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to16: {
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) { /* This is a no-op. */
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return iselWordExpr_R(env, e->Iex.Unop.arg);
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break; /* evidently not used in 32-bit mode */
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16HIto8:
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32HIto16: {
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UShort shift = toUShort(op_unop == Iop_16HIto8 ? 8 : 16);
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,shift)));
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_128HIto64:
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rHi; /* and abandon rLo .. poor wee thing :-) */
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_128to64:
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rLo; /* similar stupid comment to the above ... */
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Uto32:
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Uto8: {
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        r_dst = newVRegI(env);
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg);
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Set(cond,r_dst));
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto8:
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto16:
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto32: {
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* could do better than this, but for now ... */
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        r_dst = newVRegI(env);
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg);
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Set(cond,r_dst));
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,31)));
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,31)));
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto64:
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* could do better than this, but for now ... */
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg        r_dst = newVRegI(env);
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg);
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Set(cond,r_dst));
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        r_dst, r_dst, PPCRH_Imm(False,63)));
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        r_dst, r_dst, PPCRH_Imm(False,63)));
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r_dst;
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz32:
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz64: {
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src, r_dst;
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCUnaryOp op_clz = (op_unop == Iop_Clz32) ? Pun_CLZ32 :
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                      Pun_CLZ64;
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (op_unop == Iop_Clz64 && !mode64)
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto irreducible;
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Count leading zeroes. */
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_dst = newVRegI(env);
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(op_clz,r_dst,r_src));
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Left8:
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Left32:
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Left64: {
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src, r_dst;
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (op_unop == Iop_Left64 && !mode64)
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto irreducible;
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_dst = newVRegI(env);
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpwNEZ32: {
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, r_dst, PPCRH_Imm(False, 31)));
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpwNEZ64: {
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) goto irreducible;
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, r_dst, PPCRH_Imm(False, 63)));
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to32: {
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        r_aligned16;
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        dst  = newVRegI(env);
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        vec  = iselVecExpr(env, e->Iex.Unop.arg);
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_off0, *am_off12;
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 32 );     // Move SP down 32 bytes
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // get a quadword aligned address within our stack space
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_aligned16 = get_sp_aligned16( env );
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off0  = PPCAMode_IR( 0, r_aligned16 );
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off12 = PPCAMode_IR( 12,r_aligned16 );
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // store vec, load low word to dst
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Load( 4, dst, am_off12, mode64 ));
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 32 );       // Reset SP
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to64:
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128HIto64:
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r_aligned16;
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     dst = newVRegI(env);
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     vec = iselVecExpr(env, e->Iex.Unop.arg);
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode *am_off0, *am_off8;
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 32 );     // Move SP down 32 bytes
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // get a quadword aligned address within our stack space
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r_aligned16 = get_sp_aligned16( env );
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off0 = PPCAMode_IR( 0, r_aligned16 );
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off8 = PPCAMode_IR( 8 ,r_aligned16 );
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // store vec, load low word (+8) or high (+0) to dst
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     PPCInstr_Load(
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        8, dst,
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op_unop == Iop_V128HIto64 ? am_off0 : am_off8,
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mode64 ));
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 32 );       // Reset SP
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16to8:
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to8:
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to16:
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to8:
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* These are no-ops. */
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return iselWordExpr_R(env, e->Iex.Unop.arg);
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ReinterpF64asI64(e) */
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Given an IEEE754 double, produce an I64 with the same bit
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pattern. */
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF64asI64:
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode *am_addr;
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg r_dst  = newVRegI(env);
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );     // Move SP down 16 bytes
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // store as F64
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           fr_src, am_addr ));
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // load as Ity_I64
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );       // Reset SP
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r_dst;
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ReinterpF32asI32(e) */
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Given an IEEE754 float, produce an I32 with the same bit
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pattern. */
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF32asI32: {
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I believe this generates correct code for both 32- and
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            64-bit hosts. */
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_addr;
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegI(env);
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 16 );     // Move SP down 16 bytes
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // store as F32
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        fr_src, am_addr ));
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // load as Ity_I32
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( 4, r_dst, am_addr, mode64 ));
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 16 );       // Reset SP
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- GET --------- */
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Get: {
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8  || ty == Ity_I16 ||
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          GuestStatePtr(mode64) );
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      r_dst, am_addr, mode64 ));
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_GetI: {
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* src_am
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset( env, e->Iex.GetI.descr,
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     e->Iex.GetI.ix, e->Iex.GetI.bias );
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegI(env);
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && ty == Ity_I64) {
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( toUChar(8),
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      r_dst, src_am, mode64 ));
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((!mode64) && ty == Ity_I32) {
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( toUChar(4),
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      r_dst, src_am, mode64 ));
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- CCALL --------- */
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_CCall: {
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    r_dst = newVRegI(env);
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ty == Ity_I32);
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be very restrictive for now.  Only 32/64-bit ints allowed
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for args, and 32 bits for return type. */
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.CCall.retty != Ity_I32)
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto irreducible;
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Marshal args, do the call, clear stack. */
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall( env, False, NULL,
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.CCall.cee, e->Iex.CCall.args );
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* GPR3 now holds the destination address from Pin_Goto */
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LITERAL --------- */
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32/16/8-bit literals */
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Const: {
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Long l;
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegI(env);
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRConst* con = e->Iex.Const.con;
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (con->tag) {
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U64: if (!mode64) goto irreducible;
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       l = (Long)            con->Ico.U64; break;
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:      vpanic("iselIntExpr_R.const(ppc)");
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(r_dst, (ULong)l, mode64));
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MULTIPLEX --------- */
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Mux0X: {
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((ty == Ity_I8  || ty == Ity_I16 ||
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) &&
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode  cc = mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   rX     = iselWordExpr_R(env, e->Iex.Mux0X.exprX);
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRI* r0     = iselWordExpr_RI(env, e->Iex.Mux0X.expr0);
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst  = newVRegI(env);
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_tmp  = newVRegI(env);
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dst,rX));
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_tmp,
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_cond, PPCRH_Imm(False,0xFF)));
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, r_tmp, PPCRH_Imm(False,0)));
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_CMov(cc,r_dst,r0));
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (e->tag) */
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We get here if no pattern matched. */
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown irreducible:
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselIntExpr_R(ppc): cannot reduce tree");
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expression auxiliaries              ---*/
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AMODEs --------------------- */
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AMode which computes the value of the specified
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression, possibly also adding insns to the code list as a
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result.  The expression may only be a word-size one.
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool uInt_fits_in_16_bits ( UInt u )
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Is u the same as the sign-extend of its lower 16 bits? */
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i = u & 0xFFFF;
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i <<= 16;
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i >>= 16;
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(u == (UInt)i);
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool uLong_fits_in_16_bits ( ULong u )
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Is u the same as the sign-extend of its lower 16 bits? */
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long i = u & 0xFFFFULL;
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i <<= 48;
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i >>= 48;
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(u == (ULong)i);
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool uLong_is_4_aligned ( ULong u )
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool((u & 3ULL) == 0);
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AMode ( ISelEnv* env, PPCAMode* am )
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Pam_IR:
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Using uInt_fits_in_16_bits in 64-bit mode seems a bit bogus,
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         somehow, but I think it's OK. */
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return toBool( hregClass(am->Pam.IR.base) == HRcGPR(mode64) &&
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hregIsVirtual(am->Pam.IR.base) &&
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     uInt_fits_in_16_bits(am->Pam.IR.index) );
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Pam_RR:
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return toBool( hregClass(am->Pam.RR.base) == HRcGPR(mode64) &&
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hregIsVirtual(am->Pam.RR.base) &&
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hregClass(am->Pam.RR.index) == HRcGPR(mode64) &&
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hregIsVirtual(am->Pam.IR.index) );
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("sane_AMode: unknown ppc amode tag");
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPPCAMode* iselWordExpr_AMode ( ISelEnv* env, IRExpr* e, IRType xferTy )
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode* am = iselWordExpr_AMode_wrk(env, e, xferTy);
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sane_AMode(env, am));
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am;
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCAMode* iselWordExpr_AMode_wrk ( ISelEnv* env, IRExpr* e, IRType xferTy )
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (env->mode64) {
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the data load/store type is I32 or I64, this amode might
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         be destined for use in ld/ldu/lwa/st/stu.  In which case
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         insist that if it comes out as an _IR, the immediate must
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         have its bottom two bits be zero.  This does assume that for
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         any other type (I8/I16/I128/F32/F64/V128) the amode will not
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         be parked in any such instruction.  But that seems a
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reasonable assumption.  */
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool aligned4imm = toBool(xferTy == Ity_I32 || xferTy == Ity_I64);
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ty == Ity_I64);
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->tag == Iex_Binop
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.op == Iop_Add64
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->tag == Iex_Const
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && (aligned4imm  ? uLong_is_4_aligned(e->Iex.Binop.arg2
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                 ->Iex.Const.con->Ico.U64)
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           : True)
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && uLong_fits_in_16_bits(e->Iex.Binop.arg2
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ->Iex.Const.con->Ico.U64)) {
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             iselWordExpr_R(env, e->Iex.Binop.arg1) );
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add64(expr,expr) */
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->tag == Iex_Binop
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.op == Iop_Add64) {
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCAMode_RR( r_idx, r_base );
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ty == Ity_I32);
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->tag == Iex_Binop
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.op == Iop_Add32
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->tag == Iex_Const
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && uInt_fits_in_16_bits(e->Iex.Binop.arg2
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ->Iex.Const.con->Ico.U32)) {
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             iselWordExpr_R(env, e->Iex.Binop.arg1) );
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add32(expr,expr) */
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->tag == Iex_Binop
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.op == Iop_Add32) {
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCAMode_RR( r_idx, r_base );
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't match anything in particular.  Generate it into
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a register and use that. */
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCAMode_IR( 0, iselWordExpr_R(env,e) );
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RH --------------------- */
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (reg-or-halfword-immediate).  It's important to specify whether the
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   immediate is to be regarded as signed or not.  If yes, this will
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   never return -32768 as an immediate; this guaranteed that all
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   signed immediates that are return can have their sign inverted if
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   need be. */
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH ( ISelEnv* env, Bool syned, IRExpr* e )
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRH* ri = iselWordExpr_RH_wrk(env, syned, e);
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Imm:
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ri->Prh.Imm.syned == syned);
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (syned)
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(ri->Prh.Imm.imm16 != 0x8000);
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Reg:
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregIsVirtual(ri->Prh.Reg.reg));
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("iselIntExpr_RH: unknown ppc RH tag");
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH_wrk ( ISelEnv* env, Bool syned, IRExpr* e )
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u;
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long  l;
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8  || ty == Ity_I16 ||
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRConst* con = e->Iex.Const.con;
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* What value are we aiming to generate? */
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (con->tag) {
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Note: Not sign-extending - we carry 'syned' around */
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U64: vassert(env->mode64);
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    u =              con->Ico.U64; break;
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U32: u = 0xFFFFFFFF & con->Ico.U32; break;
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U16: u = 0x0000FFFF & con->Ico.U16; break;
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U8:  u = 0x000000FF & con->Ico.U8; break;
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:      vpanic("iselIntExpr_RH.Iex_Const(ppch)");
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      l = (Long)u;
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now figure out if it's representable. */
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!syned && u <= 65535) {
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCRH_Imm(False/*unsigned*/, toUShort(u & 0xFFFF));
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (syned && l >= -32767 && l <= 32767) {
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCRH_Imm(True/*signed*/, toUShort(u & 0xFFFF));
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no luck; use the Slow Way. */
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCRH_Reg( iselWordExpr_R ( env, e ) );
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RIs --------------------- */
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate an expression into an PPCRI operand.  As with
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, the expression can have type 32, 16 or 8 bits, or,
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in 64-bit mode, 64 bits. */
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRI* iselWordExpr_RI ( ISelEnv* env, IRExpr* e )
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRI* ri = iselWordExpr_RI_wrk(env, e);
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Pri_Imm:
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Pri_Reg:
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregClass(ri->Pri.Reg) == HRcGPR(env->mode64));
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregIsVirtual(ri->Pri.Reg));
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("iselIntExpr_RI: unknown ppc RI tag");
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRI* iselWordExpr_RI_wrk ( ISelEnv* env, IRExpr* e )
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long  l;
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8  || ty == Ity_I16 ||
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRConst* con = e->Iex.Const.con;
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (con->tag) {
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U64: vassert(env->mode64);
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    l = (Long)            con->Ico.U64; break;
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:      vpanic("iselIntExpr_RI.Iex_Const(ppch)");
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return PPCRI_Imm((ULong)l);
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCRI_Reg( iselWordExpr_R ( env, e ) );
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RH5u --------------------- */
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   being an immediate in the range 1 .. 31 inclusive.  Used for doing
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shift amounts.  Only used in 32-bit mode. */
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH5u ( ISelEnv* env, IRExpr* e )
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRH* ri;
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!env->mode64);
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ri = iselWordExpr_RH5u_wrk(env, e);
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Imm:
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 31);
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!ri->Prh.Imm.syned);
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Reg:
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregIsVirtual(ri->Prh.Reg.reg));
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("iselIntExpr_RH5u: unknown ppc RI tag");
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH5u_wrk ( ISelEnv* env, IRExpr* e )
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8);
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->tag == Ico_U8
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->Ico.U8 >= 1
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->Ico.U8 <= 31) {
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCRH_Reg( iselWordExpr_R ( env, e ) );
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RH6u --------------------- */
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   being an immediate in the range 1 .. 63 inclusive.  Used for doing
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shift amounts.  Only used in 64-bit mode. */
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH6u ( ISelEnv* env, IRExpr* e )
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRH* ri;
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env->mode64);
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ri = iselWordExpr_RH6u_wrk(env, e);
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Imm:
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 63);
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!ri->Prh.Imm.syned);
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Reg:
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregIsVirtual(ri->Prh.Reg.reg));
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("iselIntExpr_RH6u: unknown ppc64 RI tag");
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH6u_wrk ( ISelEnv* env, IRExpr* e )
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8);
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->tag == Ico_U8
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->Ico.U8 >= 1
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->Ico.U8 <= 63) {
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCRH_Reg( iselWordExpr_R ( env, e ) );
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- CONDCODE --------------------- */
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to evaluated a bit-typed expression, returning the
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condition code which would correspond when the expression would
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notionally have returned 1. */
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCCondCode iselCondCode ( ISelEnv* env, IRExpr* e )
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Uh, there's nothing we can sanity check here, unfortunately. */
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return iselCondCode_wrk(env,e);
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCCondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Constant 1:Bit */
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True) {
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Make a compare that will always be true:
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_zero = newVRegI(env);
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(r_zero, 0, env->mode64));
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r_zero, PPCRH_Reg(r_zero)));
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Not1(...) */
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate code for the arg, and negate the test condition */
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg);
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond.test = invertCondTest(cond.test);
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return cond;
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: 32to1 or 64to1 --- */
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32to1, 64to1 */
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop &&
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       (e->Iex.Unop.op == Iop_32to1 || e->Iex.Unop.op == Iop_64to1)) {
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tmp = newVRegI(env);
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* could do better, probably -- andi. */
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Alu(Palu_AND, tmp,
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 src, PPCRH_Imm(False,1)));
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, tmp, PPCRH_Imm(False,1)));
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ8 --- */
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ8(x) */
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* could do better -- andi. */
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ8) {
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg arg = iselWordExpr_R(env, e->Iex.Unop.arg);
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tmp = newVRegI(env);
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 PPCRH_Imm(False,0xFF)));
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, tmp, PPCRH_Imm(False,0)));
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ32 --- */
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ32(x) */
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ32) {
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r1 = iselWordExpr_R(env, e->Iex.Unop.arg);
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r1, PPCRH_Imm(False,0)));
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: Cmp*32* --- */
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Cmp*32*(x,y) */
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ32
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE32
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT32S
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT32U
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE32S
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE32U)) {
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S ||
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Binop.op == Iop_CmpLE32S);
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg   r1  = iselWordExpr_R(env, e->Iex.Binop.arg1);
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r1, ri2));
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNE32:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpLT32U: case Iop_CmpLT32S:
2431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
2432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpLE32U: case Iop_CmpLE32S:
2433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("iselCondCode(ppc): CmpXX32");
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ64 --- */
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ64 */
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ64) {
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!env->mode64) {
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi, lo;
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tmp = newVRegI(env);
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr( &hi, &lo, env, e->Iex.Unop.arg );
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, tmp, lo, PPCRH_Reg(hi)));
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*sign*/, True/*32bit cmp*/,
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, tmp,PPCRH_Imm(False,0)));
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {  // mode64
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Binop.arg1);
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*sign*/, False/*64bit cmp*/,
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, r_src,PPCRH_Imm(False,0)));
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: Cmp*64* --- */
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Cmp*64*(x,y) */
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ64
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE64
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT64S
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT64U
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE64S
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE64U)) {
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   syned = (e->Iex.Binop.op == Iop_CmpLT64S ||
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      e->Iex.Binop.op == Iop_CmpLE64S);
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(env->mode64);
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r1, ri2));
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNE64:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64U: return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("iselCondCode(ppc): CmpXX64");
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* var */
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_src      = lookupIRTemp(env, e->Iex.RdTmp.tmp);
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src_masked = newVRegI(env);
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env,
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               PPCInstr_Alu(Palu_AND, src_masked,
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            r_src, PPCRH_Imm(False,1)));
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env,
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            7/*cr*/, src_masked, PPCRH_Imm(False,1)));
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselCondCode(ppc): No such tag(%u)\n", e->tag);
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselCondCode(ppc)");
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (128 bit)               ---*/
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 64-bit mode ONLY: compute a 128-bit value into a register pair,
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which is returned as the first two parameters.  As with
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselWordExpr_R, these may be either real or virtual regs; in any
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case they must not be changed by subsequent code emitted by the
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   caller.  */
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt128Expr ( HReg* rHi, HReg* rLo,
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ISelEnv* env, IRExpr* e )
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env->mode64);
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselInt128Expr_wrk(rHi, rLo, env, e);
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rHi) == HRcGPR(env->mode64));
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rHi));
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rLo) == HRcGPR(env->mode64));
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rLo));
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 ISelEnv* env, IRExpr* e )
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* read 128-bit IRTemp */
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY ops --------- */
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64 x 64 -> 128 multiply */
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU64:
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS64: {
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg     tLo     = newVRegI(env);
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg     tHi     = newVRegI(env);
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool     syned   = toBool(e->Iex.Binop.op == Iop_MullS64);
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     False/*lo64*/, False/*64bit mul*/,
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tLo, r_srcL, r_srcR));
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(syned,
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     True/*hi64*/, False/*64bit mul*/,
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tHi, r_srcL, r_srcR));
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64HLto128(e1,e2) */
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLto128:
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- UNARY ops --------- */
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Unop) */
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselInt128Expr(ppc64): No such tag(%u)\n", e->tag);
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselInt128Expr(ppc64)");
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (64 bit)                ---*/
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode ONLY: compute a 64-bit value into a register pair,
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which is returned as the first two parameters.  As with
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, these may be either real or virtual regs; in any
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case they must not be changed by subsequent code emitted by the
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   caller.  */
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr ( HReg* rHi, HReg* rLo,
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            ISelEnv* env, IRExpr* e )
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!env->mode64);
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselInt64Expr_wrk(rHi, rLo, env, e);
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rHi) == HRcInt32);
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rHi));
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rLo) == HRcInt32);
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rLo));
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ISelEnv* env, IRExpr* e )
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit load */
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo    = newVRegI(env);
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi    = newVRegI(env);
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!env->mode64);
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( 4/*byte-load*/,
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   tHi, PPCAMode_IR( 0, r_addr ),
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   False/*32-bit insn please*/) );
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( 4/*byte-load*/,
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   tLo, PPCAMode_IR( 4, r_addr ),
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   False/*32-bit insn please*/) );
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit literal */
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong w64 = e->Iex.Const.con->Ico.U64;
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  wLo = ((UInt)w64) & 0xFFFFFFFF;
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg  tLo = newVRegI(env);
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg  tHi = newVRegI(env);
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_U64);
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(tHi, (Long)(Int)wHi, False/*mode32*/));
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(tLo, (Long)(Int)wLo, False/*mode32*/));
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* read 64-bit IRTemp */
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit GET */
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       GuestStatePtr(False/*mode32*/) );
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr4 = advance4(env, am_addr);
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( 4, tHi, am_addr,  False/*mode32*/ ));
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( 4, tLo, am_addr4, False/*mode32*/ ));
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit Mux0X */
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg e0Lo, e0Hi, eXLo, eXHi;
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCCondCode cc = mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_tmp  = newVRegI(env);
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0);
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr(&eXHi, &eXLo, env, e->Iex.Mux0X.exprX);
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVds_RR(tHi,eXHi));
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVds_RR(tLo,eXLo));
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Alu(Palu_AND,
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 r_tmp, r_cond, PPCRH_Imm(False,0xFF)));
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r_tmp, PPCRH_Imm(False,0)));
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_CMov(cc,tHi,PPCRI_Reg(e0Hi)));
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_CMov(cc,tLo,PPCRI_Reg(e0Lo)));
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY ops --------- */
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp op_binop = e->Iex.Binop.op;
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (op_binop) {
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 32 x 32 -> 64 multiply */
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MullU32:
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MullS32: {
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     tLo     = newVRegI(env);
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     tHi     = newVRegI(env);
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool     syned   = toBool(op_binop == Iop_MullS32);
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        False/*lo32*/, True/*32bit mul*/,
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        tLo, r_srcL, r_srcR));
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_MulL(syned,
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        True/*hi32*/, True/*32bit mul*/,
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        tHi, r_srcL, r_srcR));
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Or64/And64/Xor64 */
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Or64:
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_And64:
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Xor64: {
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xLo, xHi, yLo, yHi;
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAluOp op = (op_binop == Iop_Or64) ? Palu_OR :
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (op_binop == Iop_And64) ? Palu_AND : Palu_XOR;
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Alu(op, tHi, xHi, PPCRH_Reg(yHi)));
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Alu(op, tLo, xLo, PPCRH_Reg(yLo)));
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Add64 */
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add64: {
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xLo, xHi, yLo, yHi;
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AddSubC( True/*add*/, True /*set carry*/,
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            tLo, xLo, yLo));
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AddSubC( True/*add*/, False/*read carry*/,
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            tHi, xHi, yHi));
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 32HLto64(e1,e2) */
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32HLto64:
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* F64toI64[S|U] */
2764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_F64toI64S: case Iop_F64toI64U: {
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      tLo     = newVRegI(env);
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      tHi     = newVRegI(env);
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      r1      = StackFramePtr(env->mode64);
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2);
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      ftmp    = newVRegF(env);
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(!env->mode64);
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Set host rounding mode */
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
2779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          (op_binop == Iop_F64toI64S) ? True : False,
2780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          True, ftmp, fsrc));
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ///* Restore default FPU rounding. */
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //set_FPU_rounding_default( env );
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- UNARY ops --------- */
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ64(e) */
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpwNEZ64: {
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argHi, argLo;
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tmp1  = newVRegI(env);
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tmp2  = newVRegI(env);
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg);
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* tmp1 = argHi | argLo */
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, tmp1, argHi, PPCRH_Reg(argLo)));
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* tmp2 = (tmp1 | -tmp1) >>s 31 */
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NEG,tmp2,tmp1));
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, tmp2, tmp2, PPCRH_Reg(tmp1)));
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tmp2, tmp2, PPCRH_Imm(False, 31)));
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tmp2;
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tmp2; /* yes, really tmp2 */
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Left64 */
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Left64: {
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argHi, argLo;
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg zero32 = newVRegI(env);
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg resHi  = newVRegI(env);
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg resLo  = newVRegI(env);
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg);
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(env->mode64 == False);
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(zero32, 0, env->mode64));
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* resHi:resLo = - argHi:argLo */
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AddSubC( False/*sub*/, True/*set carry*/,
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         resLo, zero32, argLo ));
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AddSubC( False/*sub*/, False/*read carry*/,
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         resHi, zero32, argHi ));
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* resHi:resLo |= srcHi:srcLo */
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, resLo, resLo, PPCRH_Reg(argLo)));
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, resHi, resHi, PPCRH_Reg(argHi)));
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = resHi;
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = resLo;
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Sto64(e) */
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Sto64: {
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi = newVRegI(env);
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tHi, src, PPCRH_Imm(False,31)));
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = src;
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Uto64(e) */
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Uto64: {
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi = newVRegI(env);
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tLo = iselWordExpr_R(env, e->Iex.Unop.arg);
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(tHi, 0, False/*mode32*/));
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V128{HI}to64 */
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128HIto64:
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to64: {
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_aligned16;
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int  off = e->Iex.Unop.op==Iop_V128HIto64 ? 0 : 8;
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tLo = newVRegI(env);
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi = newVRegI(env);
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg vec = iselVecExpr(env, e->Iex.Unop.arg);
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_off0, *am_offLO, *am_offHI;
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 32 );     // Move SP down 32 bytes
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // get a quadword aligned address within our stack space
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_aligned16 = get_sp_aligned16( env );
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off0  = PPCAMode_IR( 0,     r_aligned16 );
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_offHI = PPCAMode_IR( off,   r_aligned16 );
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_offLO = PPCAMode_IR( off+4, r_aligned16 );
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // store as Vec128
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // load hi,lo words (of hi/lo half of vec) as Ity_I32's
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Load( 4, tHi, am_offHI, False/*mode32*/ ));
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Load( 4, tLo, am_offLO, False/*mode32*/ ));
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 32 );       // Reset SP
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* could do better than this, but for now ... */
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto64: {
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tLo = newVRegI(env);
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi = newVRegI(env);
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg);
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Set(cond,tLo));
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tLo, tLo, PPCRH_Imm(False,31)));
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tLo, tLo, PPCRH_Imm(False,31)));
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(tHi, tLo));
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Not64: {
2914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg xLo, xHi;
2915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg tmpLo = newVRegI(env);
2916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg tmpHi = newVRegI(env);
2917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg);
2918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Unary(Pun_NOT,tmpLo,xLo));
2919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Unary(Pun_NOT,tmpHi,xHi));
2920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *rHi = tmpHi;
2921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *rLo = tmpLo;
2922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
2923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
2924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ReinterpF64asI64(e) */
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Given an IEEE754 double, produce an I64 with the same bit
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pattern. */
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF64asI64: {
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_addr0, *am_addr1;
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src  = iselDblExpr(env, e->Iex.Unop.arg);
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dstLo = newVRegI(env);
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dstHi = newVRegI(env);
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 16 );     // Move SP down 16 bytes
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // store as F64
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        fr_src, am_addr0 ));
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // load hi,lo as Ity_I32's
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( 4, r_dstHi,
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      am_addr0, False/*mode32*/ ));
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( 4, r_dstLo,
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      am_addr1, False/*mode32*/ ));
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = r_dstHi;
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = r_dstLo;
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 16 );       // Reset SP
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Unop) */
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselInt64Expr(ppc): No such tag(%u)\n", e->tag);
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselInt64Expr(ppc)");
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (32 bit)         ---*/
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Nothing interesting here; really just wrappers for
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit stuff. */
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselFltExpr_wrk( env, e );
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool        mode64 = env->mode64;
2987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_F32);
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr;
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegF(env);
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_F32);
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F32/*xfer*/);
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegF(env);
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       GuestStatePtr(env->mode64) );
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4, r_dst, am_addr ));
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is quite subtle.  The only way to do the relevant
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         truncation is to do a single-precision store and then a
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         double precision load to get it back into a register.  The
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         problem is, if the data is then written to memory a second
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         time, as in
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            STbe(...) = TruncF64asF32(...)
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         then will the second truncation further alter the value?  The
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         answer is no: flds (as generated here) followed by fsts
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (generated for the STbe) is the identity function on 32-bit
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         floats, so we are safe.
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Another upshot of this is that if iselStmt can see the
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         entirety of
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            STbe(...) = TruncF64asF32(arg)
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         then it can short circuit having to deal with TruncF64asF32
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         individually; instead just compute arg into a 64-bit FP
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         register and do 'fsts' (since that itself does the
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         truncation).
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         We generate pretty poor code here (should be ok both for
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         32-bit and 64-bit mode); but it is expected that for the most
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         part the latter optimisation will apply and hence this code
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         will not often be used.
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      fsrc    = iselDblExpr(env, e->Iex.Unop.arg);
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      fdst    = newVRegF(env);
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sub_from_sp( env, 16 );
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // store as F32, hence truncating
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     fsrc, zero_r1 ));
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // and reload.  Good huh?! (sigh)
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4,
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     fdst, zero_r1 ));
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_sp( env, 16 );
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return fdst;
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64UtoF32) {
3057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (mode64) {
3058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg fdst = newVRegF(env);
3059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2);
3060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg r1   = StackFramePtr(env->mode64);
3061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3063b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Set host rounding mode */
3064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         sub_from_sp( env, 16 );
3067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
3069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       False, False,
3072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       fdst, fdst));
3073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         add_to_sp( env, 16 );
3075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ///* Restore default FPU rounding. */
3077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //set_FPU_rounding_default( env );
3078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return fdst;
3079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
3080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* 32-bit mode */
3081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg fdst = newVRegF(env);
3082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg isrcHi, isrcLo;
3083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg r1   = StackFramePtr(env->mode64);
3084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2);
3088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Set host rounding mode */
3090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         sub_from_sp( env, 16 );
3093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
3095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
3096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       False, False,
3099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       fdst, fdst));
3100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         add_to_sp( env, 16 );
3102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ///* Restore default FPU rounding. */
3104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //set_FPU_rounding_default( env );
3105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return fdst;
3106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
3107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
3109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselFltExpr(ppc): No such tag(%u)\n", e->tag);
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselFltExpr_wrk(ppc)");
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (64 bit)         ---*/
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit floating point value into a register, the identity
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of which is returned.  As with iselIntExpr_R, the reg may be either
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   real or virtual; in any case it must not be changed by subsequent
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code emitted by the caller.  */
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IEEE 754 formats.  From http://www.freesoft.org/CIE/RFC/1832/32.htm:
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Type                  S (1 bit)   E (11 bits)   F (52 bits)
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ----                  ---------   -----------   -----------
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    signalling NaN        u           2047 (max)    .0uuuuu---u
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    (with at least
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     one 1 bit)
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    quiet NaN             u           2047 (max)    .1uuuuu---u
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    negative infinity     1           2047 (max)    .000000---0
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    positive infinity     0           2047 (max)    .000000---0
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    negative zero         1           0             .000000---0
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    positive zero         0           0             .000000---0
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselDblExpr_wrk( env, e );
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcFlt64);
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_F64);
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LITERAL --------- */
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union { UInt u32x2[2]; ULong u64; Double f64; } u;
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u) == 8);
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.u64) == 8);
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.f64) == 8);
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.u32x2) == 8);
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Const.con->tag == Ico_F64) {
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u.f64 = e->Iex.Const.con->Ico.F64;
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (e->Iex.Const.con->tag == Ico_F64i) {
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u.u64 = e->Iex.Const.con->Ico.F64i;
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselDblExpr(ppc): const");
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64) {
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcHi = newVRegI(env);
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcLo = newVRegI(env);
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(r_srcHi, u.u32x2[0], mode64));
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(r_srcLo, u.u32x2[1], mode64));
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else { // mode64
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = newVRegI(env);
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(r_src, u.u64, mode64));
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LOAD --------- */
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegF(env);
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr;
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_F64);
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F64/*xfer*/);
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- GET --------- */
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegF(env);
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       GuestStatePtr(mode64) );
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ));
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- OPS --------- */
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Qop) {
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCFpOp fpop = Pfp_INVALID;
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Qop.op) {
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MAddF64:    fpop = Pfp_MADDD; break;
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MAddF64r32: fpop = Pfp_MADDS; break;
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MSubF64:    fpop = Pfp_MSUBD; break;
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MSubF64r32: fpop = Pfp_MSUBS; break;
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Pfp_INVALID) {
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegF(env);
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcML  = iselDblExpr(env, e->Iex.Qop.arg2);
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcMR  = iselDblExpr(env, e->Iex.Qop.arg3);
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcAcc = iselDblExpr(env, e->Iex.Qop.arg4);
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_mode( env, e->Iex.Qop.arg1 );
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpMulAcc(fpop, r_dst,
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               r_srcML, r_srcMR, r_srcAcc));
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Triop) {
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCFpOp fpop = Pfp_INVALID;
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Triop.op) {
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AddF64:    fpop = Pfp_ADDD; break;
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SubF64:    fpop = Pfp_SUBD; break;
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulF64:    fpop = Pfp_MULD; break;
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivF64:    fpop = Pfp_DIVD; break;
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AddF64r32: fpop = Pfp_ADDS; break;
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SubF64r32: fpop = Pfp_SUBS; break;
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulF64r32: fpop = Pfp_MULS; break;
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivF64r32: fpop = Pfp_DIVS; break;
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Pfp_INVALID) {
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegF(env);
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcL = iselDblExpr(env, e->Iex.Triop.arg2);
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcR = iselDblExpr(env, e->Iex.Triop.arg3);
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_mode( env, e->Iex.Triop.arg1 );
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpBinary(fpop, r_dst, r_srcL, r_srcR));
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCFpOp fpop = Pfp_INVALID;
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SqrtF64: fpop = Pfp_SQRT; break;
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Pfp_INVALID) {
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = newVRegF(env);
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, e->Iex.Binop.arg2);
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fr_dst;
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_RoundF64toF32) {
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegF(env);
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselDblExpr(env, e->Iex.Binop.arg2);
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpRSP(r_dst, r_src));
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         //set_FPU_rounding_default( env );
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (e->Iex.Binop.op == Iop_I64StoF64 || e->Iex.Binop.op == Iop_I64UtoF64) {
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg fdst = newVRegF(env);
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2);
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg r1   = StackFramePtr(env->mode64);
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Set host rounding mode */
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          e->Iex.Binop.op == Iop_I64StoF64,
3302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          True/*fdst is 64 bit*/,
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          fdst, fdst));
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ///* Restore default FPU rounding. */
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //set_FPU_rounding_default( env );
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return fdst;
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* 32-bit mode */
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg fdst = newVRegF(env);
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg isrcHi, isrcLo;
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg r1   = StackFramePtr(env->mode64);
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2);
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Set host rounding mode */
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          e->Iex.Binop.op == Iop_I64StoF64,
3330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          True/*fdst is 64 bit*/,
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          fdst, fdst));
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ///* Restore default FPU rounding. */
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //set_FPU_rounding_default( env );
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return fdst;
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCFpOp fpop = Pfp_INVALID;
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_NegF64:     fpop = Pfp_NEG; break;
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AbsF64:     fpop = Pfp_ABS; break;
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Est5FRSqrt: fpop = Pfp_RSQRTE; break;
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_RoundF64toF64_NegINF:  fpop = Pfp_FRIM; break;
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_RoundF64toF64_PosINF:  fpop = Pfp_FRIP; break;
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_RoundF64toF64_NEAREST: fpop = Pfp_FRIN; break;
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_RoundF64toF64_ZERO:    fpop = Pfp_FRIZ; break;
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Pfp_INVALID) {
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = newVRegF(env);
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fr_dst;
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ReinterpI64asF64: {
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Given an I64, produce an IEEE754 double with the same
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               bit pattern. */
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!mode64) {
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg r_srcHi, r_srcLo;
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return mk_LoadR64toFPR( env, r_src );
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_F32toF64: {
3379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (e->Iex.Unop.arg->tag == Iex_Unop &&
3380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     e->Iex.Unop.arg->Iex.Unop.op == Iop_ReinterpI32asF32 ) {
3381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e = e->Iex.Unop.arg;
3382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
3384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               HReg fr_dst = newVRegF(env);
3385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               PPCAMode *am_addr;
3386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               sub_from_sp( env, 16 );        // Move SP down 16 bytes
3388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               am_addr = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               // store src as Ity_I32's
3391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               addInstr(env, PPCInstr_Store( 4, am_addr, src, env->mode64 ));
3392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               // load single precision float, but the end results loads into a
3394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               // 64-bit FP register -- i.e., F64.
3395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, fr_dst, am_addr));
3396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               add_to_sp( env, 16 );          // Reset SP
3398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               return fr_dst;
3399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
3400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* this is a no-op */
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg res = iselFltExpr(env, e->Iex.Unop.arg);
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return res;
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MULTIPLEX --------- */
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cc = mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg frX    = iselDblExpr(env, e->Iex.Mux0X.exprX);
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr0    = iselDblExpr(env, e->Iex.Mux0X.expr0);
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = newVRegF(env);
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_tmp  = newVRegI(env);
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_tmp,
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_cond, PPCRH_Imm(False,0xFF)));
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary( Pfp_MOV, fr_dst, frX ));
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, r_tmp, PPCRH_Imm(False,0)));
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpCMov( cc, fr_dst, fr0 ));
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fr_dst;
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselDblExpr(ppc): No such tag(%u)\n", e->tag);
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselDblExpr_wrk(ppc)");
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: SIMD (Vector) expressions, 128 bit.         ---*/
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr ( ISelEnv* env, IRExpr* e )
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselVecExpr_wrk( env, e );
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcVec128);
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAvOp op = Pav_INVALID;
3457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   PPCAvFpOp fpop = Pavfp_INVALID;
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty = typeOfIRExpr(env->type_env,e);
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_V128);
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Guest state vectors are 16byte aligned,
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         so don't need to worry here */
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env,
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               PPCInstr_AvLdSt( True/*load*/, 16, dst,
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                PPCAMode_IR( e->Iex.Get.offset,
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             GuestStatePtr(mode64) )));
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr;
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg v_dst = newVRegV(env);
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_V128);
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_V128/*xfer*/);
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, v_dst, am_addr));
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return v_dst;
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NotV128: {
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, arg));
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ8x16: {
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg zero = newVRegV(env);
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin8x16(Pav_CMPEQU, dst, arg, zero));
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ16x8: {
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg zero = newVRegV(env);
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin16x8(Pav_CMPEQU, dst, arg, zero));
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ32x4: {
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg zero = newVRegV(env);
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, dst, arg, zero));
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Recip32Fx4:    fpop = Pavfp_RCPF;    goto do_32Fx4_unary;
3527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RSqrt32Fx4:    fpop = Pavfp_RSQRTF;  goto do_32Fx4_unary;
3528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I32UtoFx4:     fpop = Pavfp_CVTU2F;  goto do_32Fx4_unary;
3529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I32StoFx4:     fpop = Pavfp_CVTS2F;  goto do_32Fx4_unary;
3530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QFtoI32Ux4_RZ: fpop = Pavfp_QCVTF2U; goto do_32Fx4_unary;
3531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QFtoI32Sx4_RZ: fpop = Pavfp_QCVTF2S; goto do_32Fx4_unary;
3532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RoundF32x4_RM: fpop = Pavfp_ROUNDM;  goto do_32Fx4_unary;
3533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RoundF32x4_RP: fpop = Pavfp_ROUNDP;  goto do_32Fx4_unary;
3534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RoundF32x4_RN: fpop = Pavfp_ROUNDN;  goto do_32Fx4_unary;
3535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RoundF32x4_RZ: fpop = Pavfp_ROUNDZ;  goto do_32Fx4_unary;
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32Fx4_unary:
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_AvUn32Fx4(fpop, dst, arg));
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32UtoV128: {
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_aligned16, r_zeros;
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   dst = newVRegV(env);
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 32 );     // Move SP down
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Get a quadword aligned address within our stack space */
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_aligned16 = get_sp_aligned16( env );
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off0  = PPCAMode_IR( 0,  r_aligned16 );
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off4  = PPCAMode_IR( 4,  r_aligned16 );
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off8  = PPCAMode_IR( 8,  r_aligned16 );
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off12 = PPCAMode_IR( 12, r_aligned16 );
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Store zeros */
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_zeros = newVRegI(env);
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(r_zeros, 0x0, mode64));
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_off0, r_zeros, mode64 ));
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_off4, r_zeros, mode64 ));
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_off8, r_zeros, mode64 ));
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Store r_src in low word of quadword-aligned mem */
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_off12, r_src, mode64 ));
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Load word into low word of quadword vector reg */
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off12 ));
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 32 );       // Reset SP
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup8x16:
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup16x8:
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup32x4:
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mk_AvDuplicateRI(env, e->Iex.Binop.arg1);
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* switch (e->Iex.Unop.op) */
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Unop) */
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLtoV128: {
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) {
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r3, r2, r1, r0, r_aligned16;
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     dst = newVRegV(env);
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* do this via the stack (easy, convenient, etc) */
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 32 );        // Move SP down
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // get a quadword aligned address within our stack space
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r_aligned16 = get_sp_aligned16( env );
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off0  = PPCAMode_IR( 0,  r_aligned16 );
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off4  = PPCAMode_IR( 4,  r_aligned16 );
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off8  = PPCAMode_IR( 8,  r_aligned16 );
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off12 = PPCAMode_IR( 12, r_aligned16 );
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Do the less significant 64 bits */
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2);
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 4, am_off12, r0, mode64 ));
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 4, am_off8,  r1, mode64 ));
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Do the more significant 64 bits */
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1);
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 4, am_off4, r2, mode64 ));
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 4, am_off0, r3, mode64 ));
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Fetch result back from stack. */
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 32 );          // Reset SP
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     dst = newVRegV(env);
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r_aligned16;
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode *am_off0, *am_off8;
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* do this via the stack (easy, convenient, etc) */
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 32 );        // Move SP down
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // get a quadword aligned address within our stack space
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r_aligned16 = get_sp_aligned16( env );
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off0  = PPCAMode_IR( 0,  r_aligned16 );
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off8  = PPCAMode_IR( 8,  r_aligned16 );
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Store 2*I64 to stack */
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 8, am_off0, rHi, mode64 ));
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 8, am_off8, rLo, mode64 ));
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Fetch result back from stack. */
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 32 );          // Reset SP
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Add32Fx4:   fpop = Pavfp_ADDF;   goto do_32Fx4;
3644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Sub32Fx4:   fpop = Pavfp_SUBF;   goto do_32Fx4;
3645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Max32Fx4:   fpop = Pavfp_MAXF;   goto do_32Fx4;
3646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Min32Fx4:   fpop = Pavfp_MINF;   goto do_32Fx4;
3647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Mul32Fx4:   fpop = Pavfp_MULF;   goto do_32Fx4;
3648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpEQ32Fx4: fpop = Pavfp_CMPEQF; goto do_32Fx4;
3649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpGT32Fx4: fpop = Pavfp_CMPGTF; goto do_32Fx4;
3650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpGE32Fx4: fpop = Pavfp_CMPGEF; goto do_32Fx4;
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32Fx4:
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32Fx4: {
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* stay consistent with native ppc compares:
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if a left/right lane holds a nan, return zeros for that lane
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            so: le == NOT(gt OR isNan)
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          */
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg isNanLR = newVRegV(env);
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg isNanL = isNan(env, argL);
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg isNanR = isNan(env, argR);
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_OR, isNanLR,
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         isNanL, isNanR));
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin32Fx4(Pavfp_CMPGTF, dst,
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           argL, argR));
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_OR, dst, dst, isNanLR));
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AndV128:    op = Pav_AND;      goto do_AvBin;
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_OrV128:     op = Pav_OR;       goto do_AvBin;
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_XorV128:    op = Pav_XOR;      goto do_AvBin;
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvBin: {
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(op, dst, arg1, arg2));
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl8x16:    op = Pav_SHL;    goto do_AvBin8x16;
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr8x16:    op = Pav_SHR;    goto do_AvBin8x16;
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar8x16:    op = Pav_SAR;    goto do_AvBin8x16;
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol8x16:    op = Pav_ROTL;   goto do_AvBin8x16;
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI8x16: op = Pav_MRGHI;  goto do_AvBin8x16;
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO8x16: op = Pav_MRGLO;  goto do_AvBin8x16;
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x16:    op = Pav_ADDU;   goto do_AvBin8x16;
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux16:  op = Pav_QADDU;  goto do_AvBin8x16;
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx16:  op = Pav_QADDS;  goto do_AvBin8x16;
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x16:    op = Pav_SUBU;   goto do_AvBin8x16;
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux16:  op = Pav_QSUBU;  goto do_AvBin8x16;
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx16:  op = Pav_QSUBS;  goto do_AvBin8x16;
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Ux16:   op = Pav_AVGU;   goto do_AvBin8x16;
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Sx16:   op = Pav_AVGS;   goto do_AvBin8x16;
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Ux16:   op = Pav_MAXU;   goto do_AvBin8x16;
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Sx16:   op = Pav_MAXS;   goto do_AvBin8x16;
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Ux16:   op = Pav_MINU;   goto do_AvBin8x16;
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Sx16:   op = Pav_MINS;   goto do_AvBin8x16;
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven8Ux16: op = Pav_OMULU;  goto do_AvBin8x16;
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven8Sx16: op = Pav_OMULS;  goto do_AvBin8x16;
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x16:  op = Pav_CMPEQU; goto do_AvBin8x16;
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Ux16: op = Pav_CMPGTU; goto do_AvBin8x16;
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Sx16: op = Pav_CMPGTS; goto do_AvBin8x16;
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvBin8x16: {
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin8x16(op, dst, arg1, arg2));
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl16x8:    op = Pav_SHL;    goto do_AvBin16x8;
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr16x8:    op = Pav_SHR;    goto do_AvBin16x8;
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar16x8:    op = Pav_SAR;    goto do_AvBin16x8;
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol16x8:    op = Pav_ROTL;   goto do_AvBin16x8;
3728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin16to8x16:    op = Pav_PACKUU;  goto do_AvBin16x8;
3729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Uto8Ux16: op = Pav_QPACKUU; goto do_AvBin16x8;
3730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16: op = Pav_QPACKSS; goto do_AvBin16x8;
3731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_InterleaveHI16x8:  op = Pav_MRGHI;  goto do_AvBin16x8;
3732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_InterleaveLO16x8:  op = Pav_MRGLO;  goto do_AvBin16x8;
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x8:    op = Pav_ADDU;   goto do_AvBin16x8;
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Ux8:  op = Pav_QADDU;  goto do_AvBin16x8;
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx8:  op = Pav_QADDS;  goto do_AvBin16x8;
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x8:    op = Pav_SUBU;   goto do_AvBin16x8;
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Ux8:  op = Pav_QSUBU;  goto do_AvBin16x8;
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx8:  op = Pav_QSUBS;  goto do_AvBin16x8;
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Ux8:   op = Pav_AVGU;   goto do_AvBin16x8;
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Sx8:   op = Pav_AVGS;   goto do_AvBin16x8;
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Ux8:   op = Pav_MAXU;   goto do_AvBin16x8;
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Sx8:   op = Pav_MAXS;   goto do_AvBin16x8;
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Ux8:   op = Pav_MINU;   goto do_AvBin16x8;
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Sx8:   op = Pav_MINS;   goto do_AvBin16x8;
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven16Ux8: op = Pav_OMULU;  goto do_AvBin16x8;
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven16Sx8: op = Pav_OMULS;  goto do_AvBin16x8;
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16x8:  op = Pav_CMPEQU; goto do_AvBin16x8;
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Ux8: op = Pav_CMPGTU; goto do_AvBin16x8;
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Sx8: op = Pav_CMPGTS; goto do_AvBin16x8;
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvBin16x8: {
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin16x8(op, dst, arg1, arg2));
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl32x4:    op = Pav_SHL;    goto do_AvBin32x4;
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr32x4:    op = Pav_SHR;    goto do_AvBin32x4;
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar32x4:    op = Pav_SAR;    goto do_AvBin32x4;
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol32x4:    op = Pav_ROTL;   goto do_AvBin32x4;
3762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin32to16x8:    op = Pav_PACKUU;  goto do_AvBin32x4;
3763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Uto16Ux8: op = Pav_QPACKUU; goto do_AvBin32x4;
3764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8: op = Pav_QPACKSS; goto do_AvBin32x4;
3765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_InterleaveHI32x4:  op = Pav_MRGHI;  goto do_AvBin32x4;
3766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_InterleaveLO32x4:  op = Pav_MRGLO;  goto do_AvBin32x4;
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32x4:    op = Pav_ADDU;   goto do_AvBin32x4;
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Ux4:  op = Pav_QADDU;  goto do_AvBin32x4;
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Sx4:  op = Pav_QADDS;  goto do_AvBin32x4;
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32x4:    op = Pav_SUBU;   goto do_AvBin32x4;
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Ux4:  op = Pav_QSUBU;  goto do_AvBin32x4;
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Sx4:  op = Pav_QSUBS;  goto do_AvBin32x4;
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg32Ux4:   op = Pav_AVGU;   goto do_AvBin32x4;
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg32Sx4:   op = Pav_AVGS;   goto do_AvBin32x4;
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Ux4:   op = Pav_MAXU;   goto do_AvBin32x4;
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Sx4:   op = Pav_MAXS;   goto do_AvBin32x4;
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Ux4:   op = Pav_MINU;   goto do_AvBin32x4;
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Sx4:   op = Pav_MINS;   goto do_AvBin32x4;
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32x4:  op = Pav_CMPEQU; goto do_AvBin32x4;
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Ux4: op = Pav_CMPGTU; goto do_AvBin32x4;
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Sx4: op = Pav_CMPGTS; goto do_AvBin32x4;
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvBin32x4: {
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin32x4(op, dst, arg1, arg2));
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN8x16: op = Pav_SHL; goto do_AvShift8x16;
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN8x16: op = Pav_SAR; goto do_AvShift8x16;
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvShift8x16: {
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst    = newVRegV(env);
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin8x16(op, dst, r_src, v_shft));
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x8: op = Pav_SHL; goto do_AvShift16x8;
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x8: op = Pav_SHR; goto do_AvShift16x8;
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x8: op = Pav_SAR; goto do_AvShift16x8;
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvShift16x8: {
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst    = newVRegV(env);
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin16x8(op, dst, r_src, v_shft));
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x4: op = Pav_SHL; goto do_AvShift32x4;
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x4: op = Pav_SHR; goto do_AvShift32x4;
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x4: op = Pav_SAR; goto do_AvShift32x4;
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvShift32x4: {
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst    = newVRegV(env);
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin32x4(op, dst, r_src, v_shft));
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrV128: op = Pav_SHR; goto do_AvShiftV128;
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlV128: op = Pav_SHL; goto do_AvShiftV128;
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvShiftV128: {
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst    = newVRegV(env);
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: shift value gets masked by 127 */
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(op, dst, r_src, v_shft));
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Perm8x16: {
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst   = newVRegV(env);
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_src = iselVecExpr(env, e->Iex.Binop.arg1);
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_ctl = iselVecExpr(env, e->Iex.Binop.arg2);
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvPerm(dst, v_src, v_src, v_ctl));
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* switch (e->Iex.Binop.op) */
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const ) {
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_V128);
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Const.con->Ico.V128 == 0x0000) {
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return generate_zeroes_V128(env);
3850f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
3851f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      else if (e->Iex.Const.con->Ico.V128 == 0xffff) {
3852f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         return generate_ones_V128(env);
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselVecExpr(ppc) (subarch = %s): can't reduce\n",
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              LibVEX_ppVexHwCaps(mode64 ? VexArchPPC64 : VexArchPPC32,
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 env->hwcaps));
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselVecExpr_wrk(ppc)");
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Statements                                  ---*/
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselStmt ( ISelEnv* env, IRStmt* stmt )
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n -- ");
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRStmt(stmt);
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (stmt->tag) {
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- STORE --------- */
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Store: {
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IREndness end   = stmt->Ist.Store.end;
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (end != Iend_BE)
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && (tya != Ity_I32))
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && (tya != Ity_I64))
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          (mode64 && (tyd == Ity_I64))) {
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(tyd)),
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       am_addr, r_src, mode64 ));
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_F64) {
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data);
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_F32) {
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_V128) {
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_src = iselVecExpr(env, stmt->Ist.Store.data);
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_I64 && !mode64) {
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Just calculate the address in the register.  Life is too
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            short to arse around trying and possibly failing to adjust
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the offset in a 'reg+offset' style amode. */
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rHi32, rLo32;
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr( &rHi32, &rLo32, env, stmt->Ist.Store.data );
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4/*byte-store*/,
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       PPCAMode_IR( 0, r_addr ),
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       rHi32,
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       False/*32-bit insn please*/) );
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4/*byte-store*/,
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       PPCAMode_IR( 4, r_addr ),
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       rLo32,
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       False/*32-bit insn please*/) );
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- PUT --------- */
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Put: {
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8  || ty == Ity_I16 ||
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          GuestStatePtr(mode64) );
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(ty)),
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       am_addr, r_src, mode64 ));
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && ty == Ity_I64) {
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rHi, rLo;
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           GuestStatePtr(mode64) );
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr4 = advance4(env, am_addr);
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Put.data);
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_addr,  rHi, mode64 ));
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_addr4, rLo, mode64 ));
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (ty == Ity_V128) {
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Guest state vectors are 16byte aligned,
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            so don't need to worry here */
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_src = iselVecExpr(env, stmt->Ist.Put.data);
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           GuestStatePtr(mode64) );
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, stmt->Ist.Put.data);
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          GuestStatePtr(mode64) );
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        fr_src, am_addr ));
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Indexed PUT --------- */
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_PutI: {
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* dst_am
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset(
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              env, stmt->Ist.PutI.descr,
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && ty == Ity_I64) {
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data);
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( toUChar(8),
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       dst_am, r_src, mode64 ));
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((!mode64) && ty == Ity_I32) {
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data);
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( toUChar(4),
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       dst_am, r_src, mode64 ));
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TMP --------- */
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_WrTmp: {
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmp = stmt->Ist.WrTmp.tmp;
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRTemp(env->type_env, tmp);
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8  || ty == Ity_I16 ||
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = lookupIRTemp(env, tmp);
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR( r_dst, r_src ));
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && ty == Ity_I64) {
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data);
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && ty == Ity_I128) {
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt128Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data);
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I1) {
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data);
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = lookupIRTemp(env, tmp);
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Set(cond, r_dst));
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = lookupIRTemp(env, tmp);
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, stmt->Ist.WrTmp.data);
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F32) {
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = lookupIRTemp(env, tmp);
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data);
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_V128) {
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_dst = lookupIRTemp(env, tmp);
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_src = iselVecExpr(env, stmt->Ist.WrTmp.data);
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_MOV, v_dst, v_src));
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Load Linked or Store Conditional --------- */
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_LLSC: {
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res    = stmt->Ist.LLSC.result;
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType tyRes  = typeOfIRTemp(env->type_env, res);
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt->Ist.LLSC.end != Iend_BE)
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && (tyAddr != Ity_I32))
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && (tyAddr != Ity_I64))
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt->Ist.LLSC.storedata == NULL) {
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* LL */
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_addr = iselWordExpr_R( env, stmt->Ist.LLSC.addr );
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = lookupIRTemp(env, res);
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tyRes == Ity_I32) {
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_LoadL( 4, r_dst, r_addr, mode64 ));
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tyRes == Ity_I64 && mode64) {
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_LoadL( 8, r_dst, r_addr, mode64 ));
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthru */;
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* SC */
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_res  = lookupIRTemp(env, res); /* :: Ity_I1 */
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_a    = iselWordExpr_R(env, stmt->Ist.LLSC.addr);
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src  = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_tmp  = newVRegI(env);
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType tyData = typeOfIRExpr(env->type_env,
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      stmt->Ist.LLSC.storedata);
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(tyRes == Ity_I1);
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tyData == Ity_I32 || (tyData == Ity_I64 && mode64)) {
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_StoreC( tyData==Ity_I32 ? 4 : 8,
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           r_a, r_src, mode64 ));
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_MfCR( r_tmp ));
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Pshft_SHR,
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             env->mode64 ? False : True
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                /*F:64-bit, T:32-bit shift*/,
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             r_tmp, r_tmp,
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             PPCRH_Imm(False/*unsigned*/, 29)));
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Probably unnecessary, since the IR dest type is Ity_I1,
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               and so we are entitled to leave whatever junk we like
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               drifting round in the upper 31 or 63 bits of r_res.
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               However, for the sake of conservativeness .. */
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Alu(
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Palu_AND,
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             r_res, r_tmp,
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             PPCRH_Imm(False/*signed*/, 1)));
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthru */
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto stmt_fail;
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Call to DIRTY helper --------- */
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Dirty: {
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType   retty;
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty* d = stmt->Ist.Dirty.details;
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool     passBBP = False;
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->nFxState == 0)
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(!d->needsBBP);
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      passBBP = toBool(d->nFxState > 0 && d->needsBBP);
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Marshal args, do the call, clear stack. */
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall( env, passBBP, d->guard, d->cee, d->args );
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now figure out what to do with the returned value, if any. */
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->tmp == IRTemp_INVALID)
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No return value.  Nothing to do. */
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      retty = typeOfIRTemp(env->type_env, d->tmp);
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && retty == Ity_I64) {
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dstHi, r_dstLo;
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The returned value is in %r3:%r4.  Park it in the
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register-pair associated with tmp. */
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         lookupIRTempPair( &r_dstHi, &r_dstLo, env, d->tmp);
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstHi, hregPPC_GPR3(mode64)));
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstLo, hregPPC_GPR4(mode64)));
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (retty == Ity_I8  || retty == Ity_I16 ||
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          retty == Ity_I32 || ((retty == Ity_I64) && mode64)) {
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The returned value is in %r3.  Park it in the register
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            associated with tmp. */
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = lookupIRTemp(env, d->tmp);
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MEM FENCE --------- */
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_MBE:
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (stmt->Ist.MBE.event) {
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Imbe_Fence:
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_MFence());
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- INSTR MARK --------- */
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't generate any executable code ... */
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_IMark:
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- ABI HINT --------- */
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These have no meaning (denotation in the IR) and so we ignore
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      them ... if any actually made it this far. */
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_AbiHint:
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- NO-OP --------- */
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fairly self-explanatory, wouldn't you say? */
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_NoOp:
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- EXIT --------- */
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Exit: {
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCRI*      ri_dst;
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCCondCode cc;
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRConstTag tag = stmt->Ist.Exit.dst->tag;
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && (tag != Ico_U32))
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselStmt(ppc): Ist_Exit: dst is not a 32-bit value");
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && (tag != Ico_U64))
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselStmt(ppc64): Ist_Exit: dst is not a 64-bit value");
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ri_dst = iselWordExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst));
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc     = iselCondCode(env,stmt->Ist.Exit.guard);
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_RdWrLR(True, env->savedLR));
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Goto(stmt->Ist.Exit.jk, cc, ri_dst));
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default: break;
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  stmt_fail:
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRStmt(stmt);
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselStmt(ppc)");
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Basic block terminators (Nexts)             ---*/
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk )
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCCondCode cond;
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRI* ri;
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n-- goto {");
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRJumpKind(jk);
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("} ");
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(next);
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   cond = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ri = iselWordExpr_RI(env, next);
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_RdWrLR(True, env->savedLR));
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Goto(jk, cond, ri));
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Insn selector top-level                           ---*/
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate an entire BS to ppc code. */
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHInstrArray* iselSB_PPC ( IRSB* bb, VexArch      arch_host,
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    VexArchInfo* archinfo_host,
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    VexAbiInfo*  vbi )
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j;
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg     hreg, hregHI;
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ISelEnv* env;
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt     hwcaps_host = archinfo_host->hwcaps;
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool     mode64 = False;
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt     mask32, mask64;
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(arch_host == VexArchPPC32 || arch_host == VexArchPPC64);
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mode64 = arch_host == VexArchPPC64;
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* do some sanity checks */
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
4259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX;
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
4262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	   | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX;
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode64) {
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert((hwcaps_host & mask32) == 0);
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert((hwcaps_host & mask64) == 0);
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make up an initial environment to use. */
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env = LibVEX_Alloc(sizeof(ISelEnv));
4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr = 0;
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Are we being ppc32 or ppc64? */
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->mode64 = mode64;
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up output code array. */
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->code = newHInstrArray();
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy BB's type env. */
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->type_env = bb->tyenv;
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      change as we go along. */
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->n_vregmap = bb->tyenv->types_used;
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vregmap   = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* and finally ... */
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->hwcaps      = hwcaps_host;
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->previous_rm = NULL;
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vbi         = vbi;
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For each IR temporary, allocate a suitably-kinded virtual
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register. */
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   j = 0;
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < env->n_vregmap; i++) {
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      hregHI = hreg = INVALID_HREG;
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (bb->tyenv->types[i]) {
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) { hreg   = mkHReg(j++, HRcInt64,  True); break;
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {      hreg   = mkHReg(j++, HRcInt32,  True); break;
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) { hreg   = mkHReg(j++, HRcInt64,  True); break;
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {      hreg   = mkHReg(j++, HRcInt32,  True);
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hregHI = mkHReg(j++, HRcInt32,  True); break;
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I128:   vassert(mode64);
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hreg   = mkHReg(j++, HRcInt64,  True);
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       hregHI = mkHReg(j++, HRcInt64,  True); break;
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_F32:
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_F64:    hreg   = mkHReg(j++, HRcFlt64,  True); break;
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_V128:   hreg   = mkHReg(j++, HRcVec128, True); break;
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRType(bb->tyenv->types[i]);
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselBB(ppc): IRTemp type");
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env->vregmap[i]   = hreg;
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env->vregmapHI[i] = hregHI;
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr = j;
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Keep a copy of the link reg, so helper functions don't kill it. */
4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->savedLR = newVRegI(env);
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_RdWrLR(False, env->savedLR));
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, finally we can iterate over the statements. */
4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++)
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb->stmts[i])
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselStmt(env,bb->stmts[i]);
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselNext(env,bb->next,bb->jumpkind);
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* record the number of vregs we used. */
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->code->n_vregs = env->vreg_ctr;
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return env->code;
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                     host_ppc_isel.c ---*/
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4347