1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                   host_ppc_isel.c ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2004-2012 OpenWorks LLP
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "ir_match.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_generic_regs.h"
45663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "host_generic_simd64.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_ppc_defs.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* GPR register class for ppc32/64 */
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32)
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Register Usage Conventions                        ---*/
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Regs
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ------------
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR0       Reserved
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR1       Stack Pointer
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR2       not used - TOC pointer
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR3:10    Allocateable
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR11      if mode64: not used - calls by ptr / env ptr for some langs
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR12      if mode64: not used - exceptions / global linkage code
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR13      not used - Thread-specific pointer
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR14:28   Allocateable
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR29      Unused by us (reserved for the dispatcher)
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR30      AltiVec temp spill register
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR31      GuestStatePointer
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Of Allocateable regs:
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (mode64)
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GPR3:10  Caller-saved regs
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  else
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GPR3:12  Caller-saved regs
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR14:29   Callee-saved regs
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR3       [Return | Parameter] - carrying reg
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GPR4:10    Parameter-carrying regs
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Regs
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  -------------------
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FPR0:31    Allocateable
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FPR0       Caller-saved - scratch reg
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (mode64)
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FPR1:13  Caller-saved - param & return regs
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  else
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FPR1:8   Caller-saved - param & return regs
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FPR9:13  Caller-saved regs
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FPR14:31   Callee-saved regs
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Vector Regs (on processors with the VMX feature)
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  -----------
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VR0-VR1    Volatile scratch registers
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VR2-VR13   Volatile vector parameters registers
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VR14-VR19  Volatile scratch registers
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VR20-VR31  Non-volatile registers
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VRSAVE     Non-volatile 32-bit register
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- PPC FP Status & Control Register Conventions      ---*/
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Vex-generated code expects to run with the FPU set as follows: all
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  exceptions masked.  The rounding mode is set appropriately before
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  each floating point insn emitted (or left unchanged if known to be
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  correct already).  There are a few fp insns (fmr,fneg,fabs,fnabs),
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  which are unaffected by the rm and so the rounding mode is not set
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  prior to them.
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  At least on MPC7447A (Mac Mini), frsqrte is also not affected by
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  rounding mode.  At some point the ppc docs get sufficiently vague
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  that the only way to find out is to write test programs.
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notes on the FP instruction set, 6 Feb 06.
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownWhat                 exns -> CR1 ?   Sets FPRF ?   Observes RM ?
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown-------------------------------------------------------------
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmr[.]                   if .             n             n
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfneg[.]                  if .             n             n
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfabs[.]                  if .             n             n
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnabs[.]                 if .             n             n
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfadd[.]                  if .             y             y
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfadds[.]                 if .             y             y
131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovfcfid[.] (Si64->dbl)     if .             y             y
132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovfcfidU[.] (Ui64->dbl)    if .             y             y
133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovfcfids[.] (Si64->sngl)   if .             Y             Y
134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovfcfidus[.] (Ui64->sngl)  if .             Y             Y
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfcmpo (cmp, result       n                n             n
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfcmpu  to crfD)          n                n             n
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfctid[.]  (dbl->i64)     if .       ->undef             y
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfctidz[.] (dbl->i64)     if .       ->undef    rounds-to-zero
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfctiw[.]  (dbl->i32)     if .       ->undef             y
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfctiwz[.] (dbl->i32)     if .       ->undef    rounds-to-zero
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfdiv[.]                  if .             y             y
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfdivs[.]                 if .             y             y
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmadd[.]                 if .             y             y
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmadds[.]                if .             y             y
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmsub[.]                 if .             y             y
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmsubs[.]                if .             y             y
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmul[.]                  if .             y             y
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfmuls[.]                 if .             y             y
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown(note: for fnm*, rounding happens before final negation)
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnmadd[.]                if .             y             y
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnmadds[.]               if .             y             y
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnmsub[.]                if .             y             y
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfnmsubs[.]               if .             y             y
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfre[.]                   if .             y             y
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfres[.]                  if .             y             y
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfrsqrte[.]               if .             y       apparently not
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfsqrt[.]                 if .             y             y
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfsqrts[.]                if .             y             y
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfsub[.]                  if .             y             y
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfsubs[.]                 if .             y             y
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfpscr: bits 30-31 (ibm) is RM
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            24-29 (ibm) are exnmasks/non-IEEE bit, all zero
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    15-19 (ibm) is FPRF: class, <, =, >, UNord
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownppc fe(guest) makes fpscr read as all zeros except RM (and maybe FPRF
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownin future)
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmcrfs     - move fpscr field to CR field
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmtfsfi[.] - 4 bit imm moved to fpscr field
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmtfsf[.]  - move frS[low 1/2] to fpscr but using 8-bit field mask
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmtfsb1[.] - set given fpscr bit
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmtfsb0[.] - clear given fpscr bit
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmffs[.]   - move all fpscr to frD[low 1/2]
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownFor [.] presumably cr1 is set with exn summary bits, as per
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmain FP insns
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownA single precision store truncates/denormalises the in-register value,
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbut does not round it.  This is so that flds followed by fsts is
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownalways the identity.
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- misc helpers                                      ---*/
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are duplicated in guest-ppc/toIR.c */
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* unop ( IROp op, IRExpr* a )
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Unop(op, a);
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU32 ( UInt i )
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U32(i));
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* bind ( Int binder )
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binder(binder);
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISelEnv                                           ---*/
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This carries around:
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - A mapping from IRTemp to IRType, giving the type of any IRTemp we
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     might encounter.  This is computed before insn selection starts,
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     and does not change.
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - A mapping from IRTemp to HReg.  This tells the insn selector
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     which virtual register(s) are associated with each IRTemp
223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     temporary.  This is computed before insn selection starts, and
224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     does not change.  We expect this mapping to map precisely the
225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     same set of IRTemps as the type mapping does.
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         - vregmapLo    holds the primary register for the IRTemp.
228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         - vregmapMedLo holds the secondary register for the IRTemp,
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              if any is needed.  That's only for Ity_I64 temps
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              in 32 bit mode or Ity_I128 temps in 64-bit mode.
231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         - vregmapMedHi is only for dealing with Ity_I128 temps in
232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              32 bit mode.  It holds bits 95:64 (Intel numbering)
233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              of the IRTemp.
234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         - vregmapHi is also only for dealing with Ity_I128 temps
235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              in 32 bit mode.  It holds the most significant bits
236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              (127:96 in Intel numbering) of the IRTemp.
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - The code array, that is, the insns selected so far.
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - A counter, for generating new virtual registers.
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - The host subarchitecture we are selecting insns for.
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This is set at the start and does not change.
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - A Bool to tell us if the host is 32 or 64bit.
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This is set at the start and does not change.
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - An IRExpr*, which may be NULL, holding the IR expression (an
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRRoundingMode-encoded value) to which the FPU's rounding mode
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      was most recently set.  Setting to NULL is always safe.  Used to
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      avoid redundant settings of the FPU's rounding mode, as
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      described in set_FPU_rounding_mode below.
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    - A VexMiscInfo*, needed for knowing how to generate
255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      function calls for this target.
256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    - The maximum guest address of any guest insn in this block.
258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Actually, the address of the highest-addressed byte from any
259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      insn in this block.  Is set at the start and does not change.
260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      This is used for detecting jumps which are definitely
261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      forward-edges from this block, and therefore can be made
262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (chained) to the fast entry point of the destination, thereby
263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      avoiding the destination's event check.
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Constant -- are set at the start and do not change. */
269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTypeEnv* type_env;
270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              //    64-bit mode              32-bit mode
271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg*    vregmapLo;     // Low 64-bits [63:0]    Low 32-bits     [31:0]
272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg*    vregmapMedLo;  // high 64-bits[127:64]  Next 32-bits    [63:32]
273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg*    vregmapMedHi;  // unused                Next 32-bits    [95:64]
274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg*    vregmapHi;     // unused                highest 32-bits [127:96]
275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int      n_vregmap;
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 27 Jan 06: Not currently used, but should be */
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt         hwcaps;
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool         mode64;
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VexAbiInfo*  vbi;
283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool         chainingAllowed;
285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Addr64       max_ga;
286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* These are modified as we go along. */
288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HInstrArray* code;
289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int          vreg_ctr;
290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRExpr*      previous_rm;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ISelEnv;
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp >= 0);
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp < env->n_vregmap);
300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return env->vregmapLo[tmp];
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void lookupIRTempPair ( HReg* vrHI, HReg* vrLO,
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               ISelEnv* env, IRTemp tmp )
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(tmp >= 0);
307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(tmp < env->n_vregmap);
308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(env->vregmapMedLo[tmp] != INVALID_HREG);
309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrLO = env->vregmapLo[tmp];
310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrHI = env->vregmapMedLo[tmp];
311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Only for used in 32-bit mode */
314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void lookupIRTempQuad ( HReg* vrHi, HReg* vrMedHi, HReg* vrMedLo,
315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               HReg* vrLo, ISelEnv* env, IRTemp tmp )
316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!env->mode64);
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp >= 0);
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp < env->n_vregmap);
320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(env->vregmapMedLo[tmp] != INVALID_HREG);
321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrHi    = env->vregmapHi[tmp];
322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrMedHi = env->vregmapMedHi[tmp];
323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrMedLo = env->vregmapMedLo[tmp];
324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrLo    = env->vregmapLo[tmp];
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addInstr ( ISelEnv* env, PPCInstr* instr )
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addHInstr(env->code, instr);
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppPPCInstr(instr, env->mode64);
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegI ( ISelEnv* env )
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcGPR(env->mode64),
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     True/*virtual reg*/);
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegF ( ISelEnv* env )
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegV ( ISelEnv* env )
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Forward declarations                        ---*/
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are organised as iselXXX and iselXXX_wrk pairs.  The
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselXXX_wrk do the real work, but are not to be called directly.
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   checks that all returned registers are virtual.  You should not
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call the _wrk version directly.
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'Word' refers to the size of the native machine word, that is,
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   32-bit int in 32-bit mode and 64-bit int in 64-bit mode.  '2Word'
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   therefore refers to a double-width (64/128-bit) quantity in two
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   integer registers.
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode: compute an I8/I16/I32 into a GPR.
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit mode: compute an I8/I16/I32/I64 into a GPR. */
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e );
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselWordExpr_R     ( ISelEnv* env, IRExpr* e );
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode: Compute an I8/I16/I32 into a RH
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (reg-or-halfword-immediate).
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit mode: Compute an I8/I16/I32/I64 into a RH
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (reg-or-halfword-immediate).
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   It's important to specify whether the immediate is to be regarded
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   as signed or not.  If yes, this will never return -32768 as an
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   immediate; this guaranteed that all signed immediates that are
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return can have their sign inverted if need be.
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH_wrk ( ISelEnv* env,
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Bool syned, IRExpr* e );
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH     ( ISelEnv* env,
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Bool syned, IRExpr* e );
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode: compute an I32 into a RI (reg or 32-bit immediate).
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit mode: compute an I64 into a RI (reg or 64-bit immediate). */
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRI*        iselWordExpr_RI_wrk ( ISelEnv* env, IRExpr* e );
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRI*        iselWordExpr_RI     ( ISelEnv* env, IRExpr* e );
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* In 32 bit mode ONLY, compute an I8 into a
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reg-or-5-bit-unsigned-immediate, the latter being an immediate in
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the range 1 .. 31 inclusive.  Used for doing shift amounts. */
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH5u_wrk ( ISelEnv* env, IRExpr* e );
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH5u     ( ISelEnv* env, IRExpr* e );
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* In 64-bit mode ONLY, compute an I8 into a
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reg-or-6-bit-unsigned-immediate, the latter being an immediate in
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the range 1 .. 63 inclusive.  Used for doing shift amounts. */
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH6u_wrk ( ISelEnv* env, IRExpr* e );
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH*        iselWordExpr_RH6u     ( ISelEnv* env, IRExpr* e );
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode: compute an I32 into an AMode.
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit mode: compute an I64 into an AMode.
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Requires to know (xferTy) the type of data to be loaded/stored
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   using this amode.  That is so that, for 64-bit code generation, any
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode_IR returned will have an index (immediate offset) field
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that is guaranteed to be 4-aligned, if there is any chance that the
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   amode is to be used in ld/ldu/lda/std/stdu.
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Since there are no such restrictions on 32-bit insns, xferTy is
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ignored for 32-bit code generation. */
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCAMode*     iselWordExpr_AMode_wrk ( ISelEnv* env, IRExpr* e, IRType xferTy );
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCAMode*     iselWordExpr_AMode     ( ISelEnv* env, IRExpr* e, IRType xferTy );
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr_to_32x4_wrk ( HReg* rHi, HReg* rMedHi,
425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         HReg* rMedLo, HReg* rLo,
426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         ISelEnv* env, IRExpr* e );
427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr_to_32x4     ( HReg* rHi, HReg* rMedHi,
428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         HReg* rMedLo, HReg* rLo,
429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         ISelEnv* env, IRExpr* e );
430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode ONLY: compute an I64 into a GPR pair. */
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void          iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         ISelEnv* env, IRExpr* e );
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void          iselInt64Expr     ( HReg* rHi, HReg* rLo,
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         ISelEnv* env, IRExpr* e );
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void          iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          ISelEnv* env, IRExpr* e );
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void          iselInt128Expr     ( HReg* rHi, HReg* rLo,
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          ISelEnv* env, IRExpr* e );
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCCondCode   iselCondCode_wrk ( ISelEnv* env, IRExpr* e );
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCCondCode   iselCondCode     ( ISelEnv* env, IRExpr* e );
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselDblExpr_wrk ( ISelEnv* env, IRExpr* e );
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselDblExpr     ( ISelEnv* env, IRExpr* e );
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselFltExpr     ( ISelEnv* env, IRExpr* e );
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselVecExpr_wrk ( ISelEnv* env, IRExpr* e );
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselVecExpr     ( ISelEnv* env, IRExpr* e );
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 64-bit mode ONLY. */
457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg          iselDfp64Expr_wrk ( ISelEnv* env, IRExpr* e );
458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg          iselDfp64Expr     ( ISelEnv* env, IRExpr* e );
459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 64-bit mode ONLY: compute an D128 into a GPR64 pair. */
461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDfp128Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env,
462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 IRExpr* e );
463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDfp128Expr     ( HReg* rHi, HReg* rLo, ISelEnv* env,
464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 IRExpr* e );
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Misc helpers                                ---*/
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make an int reg-reg move. */
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCInstr* mk_iMOVds_RR ( HReg r_dst, HReg r_src )
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_dst) == hregClass(r_src));
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_src) ==  HRcInt32 ||
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           hregClass(r_src) ==  HRcInt64);
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCInstr_Alu(Palu_OR, r_dst, r_src, PPCRH_Reg(r_src));
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Advance/retreat %r1 by n. */
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_to_sp ( ISelEnv* env, UInt n )
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg sp = StackFramePtr(env->mode64);
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n < 256 && (n%16) == 0);
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu( Palu_ADD, sp, sp,
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               PPCRH_Imm(True,toUShort(n)) ));
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sub_from_sp ( ISelEnv* env, UInt n )
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg sp = StackFramePtr(env->mode64);
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n < 256 && (n%16) == 0);
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu( Palu_SUB, sp, sp,
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               PPCRH_Imm(True,toUShort(n)) ));
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  returns a quadword aligned address on the stack
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - copies SP, adds 16bytes, aligns to quadword.
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  use sub_from_sp(32) before calling this,
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  as expects to have 32 bytes to play with.
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg get_sp_aligned16 ( ISelEnv* env )
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg       r = newVRegI(env);
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg align16 = newVRegI(env);
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, mk_iMOVds_RR(r, StackFramePtr(env->mode64)));
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // add 16
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu( Palu_ADD, r, r,
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               PPCRH_Imm(True,toUShort(16)) ));
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // mask to quadword
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env,
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCInstr_LI(align16, 0xFFFFFFFFFFFFFFF0ULL, env->mode64));
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu(Palu_AND, r,r, PPCRH_Reg(align16)));
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Load 2*I32 regs to fp reg */
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg mk_LoadRR32toFPR ( ISelEnv* env,
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               HReg r_srcHi, HReg r_srcLo )
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg fr_dst = newVRegF(env);
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode *am_addr0, *am_addr1;
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!env->mode64);
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_srcHi) == HRcInt32);
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_srcLo) == HRcInt32);
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sub_from_sp( env, 16 );        // Move SP down 16 bytes
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am_addr1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // store hi,lo as Ity_I32's
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Store( 4, am_addr0, r_srcHi, env->mode64 ));
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Store( 4, am_addr1, r_srcLo, env->mode64 ));
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // load as float
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_sp( env, 16 );          // Reset SP
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return fr_dst;
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Load I64 reg to fp reg */
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg mk_LoadR64toFPR ( ISelEnv* env, HReg r_src )
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg fr_dst = newVRegF(env);
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode *am_addr0;
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env->mode64);
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_src) == HRcInt64);
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sub_from_sp( env, 16 );        // Move SP down 16 bytes
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // store as Ity_I64
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Store( 8, am_addr0, r_src, env->mode64 ));
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // load as float
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_sp( env, 16 );          // Reset SP
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return fr_dst;
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given an amode, return one which references 4 bytes further
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along. */
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCAMode* advance4 ( ISelEnv* env, PPCAMode* am )
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode* am4 = dopyPPCAMode( am );
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (am4->tag == Pam_IR
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && am4->Pam.IR.index + 4 <= 32767) {
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am4->Pam.IR.index += 4;
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("advance4(ppc,host)");
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am4;
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given a guest-state array descriptor, an index expression and a
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias, generate a PPCAMode pointing at the relevant piece of
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest state.  */
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPPCAMode* genGuestArrayOffset ( ISelEnv* env, IRRegArray* descr,
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr* off, Int bias )
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg rtmp, roff;
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  elemSz = sizeofIRType(descr->elemTy);
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  nElems = descr->nElems;
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  shift  = 0;
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Throw out any cases we don't need.  In theory there might be a
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      day where we need to handle others, but not today. */
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (nElems != 16 && nElems != 32)
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("genGuestArrayOffset(ppc host)(1)");
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (elemSz) {
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  shift = 2; break;
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  shift = 3; break;
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("genGuestArrayOffset(ppc host)(2)");
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bias < -100 || bias > 100) /* somewhat arbitrarily */
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("genGuestArrayOffset(ppc host)(3)");
612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (descr->base < 0 || descr->base > 5000) /* somewhat arbitrarily */
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("genGuestArrayOffset(ppc host)(4)");
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Compute off into a reg, %off.  Then return:
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addi %tmp, %off, bias (if bias != 0)
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         andi %tmp, nElems-1
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sldi %tmp, shift
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addi %tmp, %tmp, base
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ... Baseblockptr + %tmp ...
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   roff = iselWordExpr_R(env, off);
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rtmp = newVRegI(env);
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu(
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Palu_ADD,
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rtmp, roff,
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PPCRH_Imm(True/*signed*/, toUShort(bias))));
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu(
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Palu_AND,
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rtmp, rtmp,
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PPCRH_Imm(False/*unsigned*/, toUShort(nElems-1))));
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Shft(
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Pshft_SHL,
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    env->mode64 ? False : True/*F:64-bit, T:32-bit shift*/,
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rtmp, rtmp,
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PPCRH_Imm(False/*unsigned*/, toUShort(shift))));
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Alu(
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Palu_ADD,
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rtmp, rtmp,
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    PPCRH_Imm(True/*signed*/, toUShort(descr->base))));
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode_RR( GuestStatePtr(env->mode64), rtmp );
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Function call helpers                       ---*/
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Used only in doHelperCall.  See big comment in doHelperCall re
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   handling of register-parameter args.  This function figures out
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   whether evaluation of an expression might require use of a fixed
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register.  If in doubt return True (safe but suboptimal).
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool mightRequireFixedRegs ( IRExpr* e )
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_RdTmp: case Iex_Const: case Iex_Get:
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a complete function call.  guard is a Ity_Bit expression
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   indicating whether or not the call happens.  If guard==NULL, the
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call is unconditional. */
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid doHelperCall ( ISelEnv* env,
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Bool passBBP,
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    IRExpr* guard, IRCallee* cee, IRExpr** args )
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCCondCode cc;
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg        argregs[PPC_N_REGPARMS];
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg        tmpregs[PPC_N_REGPARMS];
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool        go_fast;
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int         n_args, i, argreg;
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt        argiregs;
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong       target;
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool        mode64 = env->mode64;
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Do we need to force use of an odd-even reg pair for 64-bit
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      args? */
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool regalign_int64s
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = (!mode64) && env->vbi->host_ppc32_regalign_int64_args;
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Marshal args for a call and do the call.
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If passBBP is True, %rbp (the baseblock pointer) is to be passed
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      as the first arg.
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This function only deals with a tiny set of possibilities, which
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cover all helpers in practice.  The restrictions are that only
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arguments in registers are supported, hence only PPC_N_REGPARMS x
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (mode32:32 | mode64:64) integer bits in total can be passed.
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      In fact the only supported arg type is (mode32:I32 | mode64:I64).
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Generating code which is both efficient and correct when
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      parameters are to be passed in registers is difficult, for the
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reasons elaborated in detail in comments attached to
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall() in priv/host-x86/isel.c.  Here, we use a variant
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of the method described in those comments.
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The problem is split into two cases: the fast scheme and the
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      slow scheme.  In the fast scheme, arguments are computed
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      directly into the target (real) registers.  This is only safe
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      when we can be sure that computation of each argument will not
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      trash any real registers set by computation of any other
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argument.
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      In the slow scheme, all args are first computed into vregs, and
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      once they are all done, they are moved to the relevant real
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      regs.  This always gives correct code, but it also gives a bunch
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of vreg-to-rreg moves which are usually redundant but are hard
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for the register allocator to get rid of.
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      To decide which scheme to use, all argument expressions are
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      first examined.  If they are all so simple that it is clear they
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      will be evaluated without use of any fixed registers, use the
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fast scheme, else use the slow scheme.  Note also that only
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unconditional calls may use the fast scheme, since having to
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      compute a condition expression could itself trash real
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      registers.
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Note this requires being able to examine an expression and
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      determine whether or not evaluation of it might use a fixed
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register.  That requires knowledge of how the rest of this insn
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      selector works.  Currently just the following 3 are regarded as
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      safe -- hopefully they cover the majority of arguments in
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note that the cee->regparms field is meaningless on PPC32/64 host
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (since there is only one calling convention) and so we always
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ignore it. */
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_args = 0;
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; args[i]; i++)
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_args++;
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (PPC_N_REGPARMS < n_args + (passBBP ? 1 : 0)) {
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("doHelperCall(PPC): cannot currently handle > 8 args");
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // PPC_N_REGPARMS
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[0] = hregPPC_GPR3(mode64);
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[1] = hregPPC_GPR4(mode64);
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[2] = hregPPC_GPR5(mode64);
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[3] = hregPPC_GPR6(mode64);
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[4] = hregPPC_GPR7(mode64);
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[5] = hregPPC_GPR8(mode64);
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[6] = hregPPC_GPR9(mode64);
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[7] = hregPPC_GPR10(mode64);
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argiregs = 0;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmpregs[0] = tmpregs[1] = tmpregs[2] =
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmpregs[3] = tmpregs[4] = tmpregs[5] =
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmpregs[6] = tmpregs[7] = INVALID_HREG;
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First decide which scheme (slow or fast) is to be used.  First
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assume the fast scheme, and select slow if any contraindications
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (wow) appear. */
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   go_fast = True;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) {
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard->tag == Iex_Const
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->tag == Ico_U1
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->Ico.U1 == True) {
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unconditional */
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Not manifestly unconditional -- be conservative. */
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         go_fast = False;
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (go_fast) {
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < n_args; i++) {
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mightRequireFixedRegs(args[i])) {
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            go_fast = False;
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* At this point the scheme to use has been established.  Generate
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      code to get the arg values into the argument rregs. */
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (go_fast) {
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FAST SCHEME */
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argreg = 0;
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (passBBP) {
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argiregs |= (1 << (argreg+3));
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR( argregs[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               argiregs |= (1 << (argreg+3));
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env,
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mk_iMOVds_RR( argregs[argreg],
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      iselWordExpr_R(env, args[i]) ));
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else { // Ity_I64
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg rHi, rLo;
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (regalign_int64s && (argreg%2) == 1)
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              // ppc32 ELF abi spec for passing LONG_LONG
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  argreg++;   // XXX: odd argreg => even rN
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(argreg < PPC_N_REGPARMS-1);
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               iselInt64Expr(&rHi,&rLo, env, args[i]);
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argiregs |= (1 << (argreg+3));
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argiregs |= (1 << (argreg+3));
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else { // mode64
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argiregs |= (1 << (argreg+3));
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVds_RR( argregs[argreg],
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        iselWordExpr_R(env, args[i]) ));
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argreg++;
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fast scheme only applies for unconditional calls.  Hence: */
835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SLOW SCHEME; move via temporaries */
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argreg = 0;
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (passBBP) {
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is pretty stupid; better to move directly to r3
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            after the rest of the args are done. */
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmpregs[argreg] = newVRegI(env);
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR( tmpregs[argreg],
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     GuestStatePtr(mode64) ));
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argreg++;
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < n_args; i++) {
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(argreg < PPC_N_REGPARMS);
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32 ||
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) {
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) {
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmpregs[argreg] = iselWordExpr_R(env, args[i]);
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else { // Ity_I64
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg rHi, rLo;
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (regalign_int64s && (argreg%2) == 1)
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             // ppc32 ELF abi spec for passing LONG_LONG
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  argreg++;  // XXX: odd argreg => even rN
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(argreg < PPC_N_REGPARMS-1);
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               iselInt64Expr(&rHi,&rLo, env, args[i]);
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmpregs[argreg++] = rHi;
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmpregs[argreg]   = rLo;
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else { // mode64
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmpregs[argreg] = iselWordExpr_R(env, args[i]);
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argreg++;
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now we can compute the condition.  We can't do it earlier
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         because the argument computations could trash the condition
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         codes.  Be a bit clever to handle the common case where the
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         guard is 1:Bit. */
878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard) {
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (guard->tag == Iex_Const
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && guard->Iex.Const.con->tag == Ico_U1
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && guard->Iex.Const.con->Ico.U1 == True) {
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* unconditional -- do nothing */
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cc = iselCondCode( env, guard );
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Move the args to their final destinations. */
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < argreg; i++) {
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tmpregs[i] == INVALID_HREG)  // Skip invalid regs
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* None of these insns, including any spill code that might
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            be generated, may alter the condition codes. */
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argiregs |= (1 << (i+3));
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) );
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   target = mode64 ? Ptr_to_ULong(cee->addr) :
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     toUInt(Ptr_to_ULong(cee->addr));
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, the call itself. */
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs ));
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: FP rounding mode helpers                    ---*/
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown///* Set FPU's rounding mode to the default */
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//static
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//void set_FPU_rounding_default ( ISelEnv* env )
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//{
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   HReg fr_src = newVRegF(env);
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   HReg r_src  = newVRegI(env);
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   /* Default rounding mode = 0x0
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      Only supporting the rounding-mode bits - the rest of FPSCR is 0x0
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//       - so we can set the whole register at once (faster)
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      note: upper 32 bits ignored by FpLdFPSCR
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   */
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   addInstr(env, PPCInstr_LI(r_src, 0x0, env->mode64));
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (env->mode64) {
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fr_src = mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   } else {
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fr_src = mk_LoadRR32toFPR( env, r_src, r_src ); // 2*I32 -> F64
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   addInstr(env, PPCInstr_FpLdFPSCR( fr_src ));
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//}
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Convert IR rounding mode to PPC encoding */
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg roundModeIRtoPPC ( ISelEnv* env, HReg r_rmIR )
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   rounding mode                     | PPC  |  IR
939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   -----------------------------------------------
940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   to nearest, ties to even          | 000  | 000
941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   to zero                           | 001  | 011
942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   to +infinity                      | 010  | 010
943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   to -infinity                      | 011  | 001
944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   +++++ Below are the extended rounding modes for decimal floating point +++++
945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   to nearest, ties away from 0      | 100  | 100
946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   to nearest, ties toward 0         | 101  | 111
947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   to away from 0                    | 110  | 110
948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   to prepare for shorter precision  | 111  | 101
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r_rmPPC = newVRegI(env);
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r_tmp1  = newVRegI(env);
952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg r_tmp2  = newVRegI(env);
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r_rmIR) == HRcGPR(env->mode64));
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // r_rmPPC = XOR(r_rmIR, r_rmIR << 1) & 3
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // slwi  tmp1,    r_rmIR, 1
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // xor   tmp1,    r_rmIR, tmp1
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // andi  r_rmPPC, tmp1, 3
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               r_tmp1, r_rmIR, PPCRH_Imm(False,1)));
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr( env, PPCInstr_Alu( Palu_AND,
966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                r_tmp2, r_tmp1, PPCRH_Imm( False, 3 ) ) );
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr( env, PPCInstr_Alu( Palu_XOR,
969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                r_rmPPC, r_rmIR, PPCRH_Reg( r_tmp2 ) ) );
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r_rmPPC;
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the FPU's rounding mode: 'mode' is an I32-typed expression
976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   denoting a value in the range 0 .. 7, indicating a round mode
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   encoded as per type IRRoundingMode.  Set the PPC FPSCR to have the
978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   same rounding.  When the dfp_rm arg is True, set the decimal
979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   floating point rounding mode bits (29:31); otherwise, set the
980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   binary floating point rounding mode bits (62:63).
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For speed & simplicity, we're setting the *entire* FPSCR here.
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Setting the rounding mode is expensive.  So this function tries to
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   avoid repeatedly setting the rounding mode to the same thing by
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   first comparing 'mode' to the 'mode' tree supplied in the previous
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call to this function, if any.  (The previous value is stored in
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->previous_rm.)  If 'mode' is a single IR temporary 't' and
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->previous_rm is also just 't', then the setting is skipped.
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is safe because of the SSA property of IR: an IR temporary can
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   only be defined once and so will have the same value regardless of
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   where it appears in the block.  Cool stuff, SSA.
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A safety condition: all attempts to set the RM must be aware of
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this mechanism - by being routed through the functions here.
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Of course this only helps if blocks where the RM is set more than
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   once and it is set to the same value each time, *and* that value is
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   held in the same IR temporary each time.  In order to assure the
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   latter as much as possible, the IR optimiser takes care to do CSE
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   on any block with any sign of floating point activity.
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid _set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode, Bool dfp_rm )
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg fr_src = newVRegF(env);
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r_src;
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,mode) == Ity_I32);
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Do we need to do anything? */
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (env->previous_rm
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && env->previous_rm->tag == Iex_RdTmp
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && mode->tag == Iex_RdTmp
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && env->previous_rm->Iex.RdTmp.tmp == mode->Iex.RdTmp.tmp) {
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no - setting it to what it was before.  */
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(typeOfIRExpr(env->type_env, env->previous_rm) == Ity_I32);
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* No luck - we better set it, and remember what we set it to. */
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->previous_rm = mode;
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Only supporting the rounding-mode bits - the rest of FPSCR is
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0x0 - so we can set the whole register at once (faster). */
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Resolve rounding mode and convert to PPC representation
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r_src = roundModeIRtoPPC( env, iselWordExpr_R(env, mode) );
1030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // gpr -> fpr
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (env->mode64) {
1033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (dfp_rm) {
1034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_tmp1 = newVRegI( env );
1035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env,
1036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   PPCInstr_Shft( Pshft_SHL, False/*64bit shift*/,
1037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  r_tmp1, r_src, PPCRH_Imm( False, 32 ) ) );
1038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fr_src = mk_LoadR64toFPR( env, r_tmp1 );
1039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
1040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fr_src = mk_LoadR64toFPR( env, r_src ); // 1*I64 -> F64
1041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (dfp_rm) {
1044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_zero = newVRegI( env );
1045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, PPCInstr_LI( r_zero, 0, env->mode64 ) );
1046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fr_src = mk_LoadRR32toFPR( env, r_src, r_zero );
1047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
1048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fr_src = mk_LoadRR32toFPR( env, r_src, r_src ); // 2*I32 -> F64
1049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Move to FPSCR
1053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, PPCInstr_FpLdFPSCR( fr_src, dfp_rm ));
1054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
1057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   _set_FPU_rounding_mode(env, mode, False);
1059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void set_FPU_DFP_rounding_mode ( ISelEnv* env, IRExpr* mode )
1062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   _set_FPU_rounding_mode(env, mode, True);
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: vector helpers                              ---*/
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate all-zeroes into a new vector register.
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg generate_zeroes_V128 ( ISelEnv* env )
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg dst = newVRegV(env);
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBinary(Pav_XOR, dst, dst, dst));
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dst;
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1080f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* Generate all-ones into a new vector register.
1081f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root*/
1082f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootstatic HReg generate_ones_V128 ( ISelEnv* env )
1083f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root{
1084f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   HReg dst = newVRegV(env);
1085f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   PPCVI5s * src = PPCVI5s_Imm(-1);
1086f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   addInstr(env, PPCInstr_AvSplat(8, dst, src));
1087f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   return dst;
1088f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root}
1089f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Generates code for AvSplat
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  - takes in IRExpr* of type 8|16|32
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    returns vector reg of duplicated lanes of input
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  - uses AvSplat(imm) for imms up to simm6.
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    otherwise must use store reg & load vector
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg mk_AvDuplicateRI( ISelEnv* env, IRExpr* e )
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg   r_src;
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg   dst = newVRegV(env);
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRI* ri  = iselWordExpr_RI(env, e);
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty  = typeOfIRExpr(env->type_env,e);
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   sz  = (ty == Ity_I8) ? 8 : (ty == Ity_I16) ? 16 : 32;
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ri->tag == Pri_Imm) {
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int simm32 = (Int)ri->Pri.Imm;
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* figure out if it's do-able with imm splats. */
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (simm32 >= -32 && simm32 <= 31) {
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Char simm6 = (Char)simm32;
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (simm6 > 15) {           /* 16:31 inclusive */
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg v1 = newVRegV(env);
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg v2 = newVRegV(env);
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvSplat(sz, v1, PPCVI5s_Imm(-16)));
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvSplat(sz, v2, PPCVI5s_Imm(simm6-16)));
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sz== 8) ? PPCInstr_AvBin8x16(Pav_SUBU, dst, v2, v1) :
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sz==16) ? PPCInstr_AvBin16x8(Pav_SUBU, dst, v2, v1)
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        : PPCInstr_AvBin32x4(Pav_SUBU, dst, v2, v1) );
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (simm6 < -16) {          /* -32:-17 inclusive */
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg v1 = newVRegV(env);
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg v2 = newVRegV(env);
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvSplat(sz, v1, PPCVI5s_Imm(-16)));
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvSplat(sz, v2, PPCVI5s_Imm(simm6+16)));
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sz== 8) ? PPCInstr_AvBin8x16(Pav_ADDU, dst, v2, v1) :
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sz==16) ? PPCInstr_AvBin16x8(Pav_ADDU, dst, v2, v1)
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        : PPCInstr_AvBin32x4(Pav_ADDU, dst, v2, v1) );
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* simplest form:              -16:15 inclusive */
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvSplat(sz, dst, PPCVI5s_Imm(simm6)));
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no luck; use the Slow way. */
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r_src = newVRegI(env);
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(r_src, (Long)simm32, env->mode64));
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r_src = ri->Pri.Reg;
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: store r_src in lowest lane of 16-aligned mem,
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      load vector, splat lowest lane to dst */
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CAB: Maybe faster to store r_src multiple times (sz dependent),
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              and simply load the vector? */
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_aligned16;
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg v_src = newVRegV(env);
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode *am_off12;
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sub_from_sp( env, 32 );     // Move SP down
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Get a 16-aligned address within our stack space */
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r_aligned16 = get_sp_aligned16( env );
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_off12 = PPCAMode_IR( 12, r_aligned16 );
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Store r_src in low word of 16-aligned mem */
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Store( 4, am_off12, r_src, env->mode64 ));
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Load src to vector[low lane] */
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, v_src, am_off12 ) );
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_sp( env, 32 );       // Reset SP
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Finally, splat v_src[low_lane] to dst */
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_AvSplat(sz, dst, PPCVI5s_Reg(v_src)));
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* for each lane of vSrc: lane == nan ? laneX = all 1's : all 0's */
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg isNan ( ISelEnv* env, HReg vSrc )
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg zeros, msk_exp, msk_mnt, expt, mnts, vIsNan;
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(vSrc) == HRcVec128);
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   zeros   = mk_AvDuplicateRI(env, mkU32(0));
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   msk_exp = mk_AvDuplicateRI(env, mkU32(0x7F800000));
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   msk_mnt = mk_AvDuplicateRI(env, mkU32(0x7FFFFF));
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expt    = newVRegV(env);
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mnts    = newVRegV(env);
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vIsNan  = newVRegV(env);
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32bit float => sign(1) | exponent(8) | mantissa(23)
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nan => exponent all ones, mantissa > 0 */
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBinary(Pav_AND, expt, vSrc, msk_exp));
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, expt, expt, msk_exp));
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBinary(Pav_AND, mnts, vSrc, msk_mnt));
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBin32x4(Pav_CMPGTU, mnts, mnts, zeros));
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, PPCInstr_AvBinary(Pav_AND, vIsNan, expt, mnts));
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return vIsNan;
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select insns for an integer-typed expression, and add them to the
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code list.  Return a reg holding the result.  This reg will be a
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   want to modify it, ask for a new vreg, copy it in there, and modify
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the copy.  The register allocator will do its best to map both
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vregs to the same real register, so the copies will often disappear
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   later in the game.
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This should handle expressions of 64, 32, 16 and 8-bit type.
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   All results are returned in a (mode64 ? 64bit : 32bit) register.
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are arbitrary, so you should mask or sign extend partial values
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if necessary.
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselWordExpr_R ( ISelEnv* env, IRExpr* e )
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselWordExpr_R_wrk(env, e);
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcGPR(env->mode64));
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e )
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MatchInfo mi;
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DECLARE_PATTERN(p_32to1_then_1Uto8);
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8 || ty == Ity_I16 ||
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ty == Ity_I32 || ((ty == Ity_I64) && mode64));
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TEMP --------- */
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_RdTmp:
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LOAD --------- */
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Load: {
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      r_dst;
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr;
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Load.end != Iend_BE)
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto irreducible;
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r_dst   = newVRegI(env);
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_addr = iselWordExpr_AMode( env, e->Iex.Load.addr, ty/*of xfer*/ );
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   r_dst, am_addr, mode64 ));
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY OP --------- */
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Binop: {
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAluOp  aluOp;
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCShftOp shftOp;
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Is it an addition or logical style op? */
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8: case Iop_Add16: case Iop_Add32: case Iop_Add64:
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_ADD; break;
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: case Iop_Sub64:
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_SUB; break;
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_And8: case Iop_And16: case Iop_And32: case Iop_And64:
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_AND; break;
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Or8:  case Iop_Or16:  case Iop_Or32:  case Iop_Or64:
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_OR; break;
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: case Iop_Xor64:
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_XOR; break;
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         aluOp = Palu_INVALID; break;
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* For commutative ops we assume any literal
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         values are on the second operand. */
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (aluOp != Palu_INVALID) {
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst   = newVRegI(env);
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRH* ri_srcR = NULL;
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get right arg into an RH, in the appropriate way */
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (aluOp) {
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Palu_ADD: case Palu_SUB:
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ri_srcR = iselWordExpr_RH(env, True/*signed*/,
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      e->Iex.Binop.arg2);
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Palu_AND: case Palu_OR: case Palu_XOR:
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ri_srcR = iselWordExpr_RH(env, False/*signed*/,
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      e->Iex.Binop.arg2);
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("iselWordExpr_R_wrk-aluOp-arg2");
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* a shift? */
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl8: case Iop_Shl16: case Iop_Shl32: case Iop_Shl64:
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shftOp = Pshft_SHL; break;
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr8: case Iop_Shr16: case Iop_Shr32: case Iop_Shr64:
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shftOp = Pshft_SHR; break;
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar8: case Iop_Sar16: case Iop_Sar32: case Iop_Sar64:
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shftOp = Pshft_SAR; break;
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shftOp = Pshft_INVALID; break;
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* we assume any literal values are on the second operand. */
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shftOp != Pshft_INVALID) {
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst   = newVRegI(env);
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRH* ri_srcR = NULL;
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get right arg into an RH, in the appropriate way */
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (shftOp) {
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Pshft_SHL: case Pshft_SHR: case Pshft_SAR:
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!mode64)
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2);
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("iselIntExpr_R_wrk-shftOp-arg2");
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* widen the left arg if needed */
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (shftOp == Pshft_SHR || shftOp == Pshft_SAR) {
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ty == Ity_I8 || ty == Ity_I16) {
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               PPCRH* amt = PPCRH_Imm(False,
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      toUShort(ty == Ity_I8 ? 24 : 16));
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg   tmp = newVRegI(env);
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, PPCInstr_Shft(Pshft_SHL,
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           True/*32bit shift*/,
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           tmp, r_srcL, amt));
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, PPCInstr_Shft(shftOp,
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           True/*32bit shift*/,
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           tmp, tmp,    amt));
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               r_srcL = tmp;
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0); /* AWAITING TEST CASE */
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Only 64 expressions need 64bit shifts,
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            32bit shifts are fine for all others */
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ty == Ity_I64) {
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(mode64);
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(shftOp, False/*64bit shift*/,
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        r_dst, r_srcL, ri_srcR));
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(shftOp, True/*32bit shift*/,
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        r_dst, r_srcL, ri_srcR));
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* How about a div? */
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_DivS32 ||
1367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          e->Iex.Binop.op == Iop_DivU32 ||
1368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          e->Iex.Binop.op == Iop_DivS32E ||
1369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          e->Iex.Binop.op == Iop_DivU32E) {
1370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS32) || (e->Iex.Binop.op == Iop_DivS32E));
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegI(env);
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr( env,
1375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivU32E )
1376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             || ( e->Iex.Binop.op == Iop_DivS32E ) ) ? True
1377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                                                     : False,
1378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    syned,
1379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    True/*32bit div*/,
1380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_dst,
1381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_srcL,
1382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_srcR ) );
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_DivS64 ||
1386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          e->Iex.Binop.op == Iop_DivU64 || e->Iex.Binop.op == Iop_DivS64E
1387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          || e->Iex.Binop.op == Iop_DivU64E ) {
1388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS64) ||(e->Iex.Binop.op == Iop_DivS64E));
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegI(env);
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr( env,
1394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivS64E )
1395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             || ( e->Iex.Binop.op
1396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                      == Iop_DivU64E ) ) ? True
1397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                                         : False,
1398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    syned,
1399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    False/*64bit div*/,
1400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_dst,
1401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_srcL,
1402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    r_srcR ) );
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* No? Anyone for a mul? */
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_Mul32
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_Mul64) {
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool syned       = False;
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool sz32        = (e->Iex.Binop.op != Iop_Mul64);
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst       = newVRegI(env);
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcL      = iselWordExpr_R(env, e->Iex.Binop.arg1);
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcR      = iselWordExpr_R(env, e->Iex.Binop.arg2);
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(syned, False/*lo32*/, sz32,
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, r_srcL, r_srcR));
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32 x 32 -> 64 multiply */
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && (e->Iex.Binop.op == Iop_MullU32
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || e->Iex.Binop.op == Iop_MullS32)) {
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tLo    = newVRegI(env);
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi    = newVRegI(env);
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegI(env);
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool syned  = toBool(e->Iex.Binop.op == Iop_MullS32);
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     False/*lo32*/, True/*32bit mul*/,
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tLo, r_srcL, r_srcR));
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(syned,
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     True/*hi32*/, True/*32bit mul*/,
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tHi, r_srcL, r_srcR));
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, tHi, PPCRH_Imm(False,32)));
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR,
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_dst, r_dst, PPCRH_Reg(tLo)));
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* El-mutanto 3-way compare? */
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_CmpORD32S
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_CmpORD32U) {
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD32S);
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   dst   = newVRegI(env);
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, srcL, srcR));
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MfCR(dst));
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    PPCRH_Imm(False,7<<1)));
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_CmpORD64S
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_CmpORD64U) {
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD64S);
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   dst   = newVRegI(env);
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, srcL, srcR));
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MfCR(dst));
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    PPCRH_Imm(False,7<<1)));
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_Max32U) {
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        r1   = iselWordExpr_R(env, e->Iex.Binop.arg1);
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        r2   = iselWordExpr_R(env, e->Iex.Binop.arg2);
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        rdst = newVRegI(env);
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cc   = mk_PPCCondCode( Pct_TRUE, Pcf_7LT );
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(rdst, r1));
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, rdst, PPCRH_Reg(r2)));
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_CMov(cc, rdst, PPCRI_Reg(r2)));
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rdst;
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_32HLto64) {
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_Hi  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_Lo  = iselWordExpr_R(env, e->Iex.Binop.arg2);
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   msk   = newVRegI(env);
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* r_dst = OR( r_Hi<<32, r_Lo ) */
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, r_Hi, PPCRH_Imm(False,32)));
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(msk, 0xFFFFFFFF, mode64));
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu( Palu_AND, r_Lo, r_Lo,
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Reg(msk) ));
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu( Palu_OR, r_dst, r_dst,
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Reg(r_Lo) ));
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((e->Iex.Binop.op == Iop_CmpF64) ||
1502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (e->Iex.Binop.op == Iop_CmpD64) ||
1503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (e->Iex.Binop.op == Iop_CmpD128)) {
1504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_srcL;
1505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_srcL_lo;
1506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_srcR;
1507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_srcR_lo;
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccPPC   = newVRegI(env);
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccIR    = newVRegI(env);
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccIR_b0 = newVRegI(env);
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccIR_b2 = newVRegI(env);
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_ccIR_b6 = newVRegI(env);
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_CmpF64) {
1516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
1517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
1518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_FpCmp(r_ccPPC, fr_srcL, fr_srcR));
1519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else if (e->Iex.Binop.op == Iop_CmpD64) {
1521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fr_srcL = iselDfp64Expr(env, e->Iex.Binop.arg1);
1522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2);
1523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_Dfp64Cmp(r_ccPPC, fr_srcL, fr_srcR));
1524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {    //  e->Iex.Binop.op == Iop_CmpD128
1526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselDfp128Expr(&fr_srcL, &fr_srcL_lo, env, e->Iex.Binop.arg1);
1527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselDfp128Expr(&fr_srcR, &fr_srcR_lo, env, e->Iex.Binop.arg2);
1528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_Dfp128Cmp(r_ccPPC, fr_srcL, fr_srcL_lo,
1529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             fr_srcR, fr_srcR_lo));
1530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Map compare result from PPC to IR,
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            conforming to CmpF64 definition. */
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           FP cmp result | PPC | IR
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           --------------------------
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           UN            | 0x1 | 0x45
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           EQ            | 0x2 | 0x40
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           GT            | 0x4 | 0x00
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           LT            | 0x8 | 0x01
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // r_ccIR_b0 = r_ccPPC[0] | r_ccPPC[3]
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_ccIR_b0, r_ccPPC,
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Imm(False,0x3)));
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b0,
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccPPC,   PPCRH_Reg(r_ccIR_b0)));
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b0,
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR_b0, PPCRH_Imm(False,0x1)));
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // r_ccIR_b2 = r_ccPPC[0]
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_ccIR_b2, r_ccPPC,
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Imm(False,0x2)));
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b2,
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR_b2, PPCRH_Imm(False,0x4)));
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // r_ccIR_b6 = r_ccPPC[0] | r_ccPPC[1]
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_ccIR_b6, r_ccPPC,
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Imm(False,0x1)));
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b6,
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccPPC, PPCRH_Reg(r_ccIR_b6)));
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_ccIR_b6, r_ccIR_b6,
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     PPCRH_Imm(False,0x6)));
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b6,
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR_b6, PPCRH_Imm(False,0x40)));
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR_b0, PPCRH_Reg(r_ccIR_b2)));
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_ccIR,    PPCRH_Reg(r_ccIR_b6)));
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_ccIR;
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if ( e->Iex.Binop.op == Iop_F64toI32S ||
1580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e->Iex.Binop.op == Iop_F64toI32U ) {
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This works in both mode64 and mode32. */
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      r1      = StackFramePtr(env->mode64);
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2);
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      ftmp    = newVRegF(env);
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      idst    = newVRegI(env);
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Set host rounding mode */
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 16 );
1592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/,
1593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       e->Iex.Binop.op == Iop_F64toI32S ? True/*syned*/
1594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                                     : False,
1595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       True/*flt64*/,
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       ftmp, fsrc));
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpSTFIW(r1, ftmp));
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load(4, idst, zero_r1, mode64));
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* in 64-bit mode we need to sign-widen idst. */
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64)
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Unary(Pun_EXTSW, idst, idst));
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 16 );
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ///* Restore default FPU rounding. */
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         //set_FPU_rounding_default( env );
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return idst;
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (e->Iex.Binop.op == Iop_F64toI64S || e->Iex.Binop.op == Iop_F64toI64U ) {
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      r1      = StackFramePtr(env->mode64);
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2);
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      idst    = newVRegI(env);
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      ftmp    = newVRegF(env);
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Set host rounding mode */
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
1624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          ( e->Iex.Binop.op == Iop_F64toI64S ) ? True
1625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                                            : False,
1626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          True, ftmp, fsrc));
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ///* Restore default FPU rounding. */
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //set_FPU_rounding_default( env );
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return idst;
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- UNARY OP --------- */
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Unop: {
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp op_unop = e->Iex.Unop.op;
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 1Uto8(32to1(expr32)) */
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DEFINE_PATTERN(p_32to1_then_1Uto8,
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* expr32 = mi.bindee[0];
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, expr32);
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_dst,
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_src, PPCRH_Imm(False,1)));
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 16Uto32(LDbe:I16(expr32)) */
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DECLARE_PATTERN(p_LDbe16_then_16Uto32);
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN(p_LDbe16_then_16Uto32,
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_16Uto32,
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Load(Iend_BE,Ity_I16,bind(0))) );
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi,p_LDbe16_then_16Uto32,e)) {
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg r_dst = newVRegI(env);
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* amode
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = iselWordExpr_AMode( env, mi.bindee[0], Ity_I16/*xfer*/ );
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load(2,r_dst,amode, mode64));
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r_dst;
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (op_unop) {
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto16:
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto32:
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Uto64:
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Uto32:
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Uto64: {
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UShort mask  = toUShort(op_unop==Iop_16Uto64 ? 0xFFFF :
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 op_unop==Iop_16Uto32 ? 0xFFFF : 0xFF);
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND,r_dst,r_src,
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    PPCRH_Imm(False,mask)));
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Uto64: {
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,32)));
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,32)));
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto16:
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto32:
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Sto32: {
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UShort amt   = toUShort(op_unop==Iop_16Sto32 ? 16 : 24);
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,amt)));
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,amt)));
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_8Sto64:
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16Sto64: {
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UShort amt   = toUShort(op_unop==Iop_8Sto64  ? 56 : 48);
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mode64);
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,amt)));
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,amt)));
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Sto64: {
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 vassert(mode64);
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* According to the IBM docs, in 64 bit mode, srawi r,r,0
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sign extends the lower 32 bits into the upper 32 bits. */
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,0)));
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not8:
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not16:
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not32:
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Not64: {
1740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (op_unop == Iop_Not64) vassert(mode64);
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NOT,r_dst,r_src));
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HIto32: {
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) {
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rHi; /* and abandon rLo .. poor wee thing :-) */
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg   r_dst = newVRegI(env);
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   r_dst, r_src, PPCRH_Imm(False,32)));
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r_dst;
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to32: {
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) {
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rLo; /* similar stupid comment to the above ... */
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* This is a no-op. */
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return iselWordExpr_R(env, e->Iex.Unop.arg);
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to16: {
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) { /* This is a no-op. */
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return iselWordExpr_R(env, e->Iex.Unop.arg);
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break; /* evidently not used in 32-bit mode */
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16HIto8:
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32HIto16: {
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst = newVRegI(env);
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UShort shift = toUShort(op_unop == Iop_16HIto8 ? 8 : 16);
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_src, PPCRH_Imm(False,shift)));
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_128HIto64:
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rHi; /* and abandon rLo .. poor wee thing :-) */
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_128to64:
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rLo; /* similar stupid comment to the above ... */
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_1Uto64:
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Uto32:
1802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_1Uto8:
1803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if ((op_unop != Iop_1Uto64) || mode64) {
1804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg        r_dst = newVRegI(env);
1805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg);
1806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_Set(cond,r_dst));
1807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto8:
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto16:
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto32: {
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* could do better than this, but for now ... */
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        r_dst = newVRegI(env);
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg);
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Set(cond,r_dst));
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,31)));
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                r_dst, r_dst, PPCRH_Imm(False,31)));
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto64:
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* could do better than this, but for now ... */
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg        r_dst = newVRegI(env);
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg);
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Set(cond,r_dst));
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        r_dst, r_dst, PPCRH_Imm(False,63)));
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        r_dst, r_dst, PPCRH_Imm(False,63)));
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r_dst;
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz32:
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Clz64: {
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src, r_dst;
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCUnaryOp op_clz = (op_unop == Iop_Clz32) ? Pun_CLZ32 :
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                      Pun_CLZ64;
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (op_unop == Iop_Clz64 && !mode64)
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto irreducible;
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Count leading zeroes. */
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_dst = newVRegI(env);
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(op_clz,r_dst,r_src));
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Left8:
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Left32:
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Left64: {
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src, r_dst;
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (op_unop == Iop_Left64 && !mode64)
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto irreducible;
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_dst = newVRegI(env);
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpwNEZ32: {
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, r_dst, PPCRH_Imm(False, 31)));
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpwNEZ64: {
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) goto irreducible;
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     r_dst, r_dst, PPCRH_Imm(False, 63)));
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to32: {
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        r_aligned16;
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        dst  = newVRegI(env);
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        vec  = iselVecExpr(env, e->Iex.Unop.arg);
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_off0, *am_off12;
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 32 );     // Move SP down 32 bytes
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // get a quadword aligned address within our stack space
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_aligned16 = get_sp_aligned16( env );
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off0  = PPCAMode_IR( 0, r_aligned16 );
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off12 = PPCAMode_IR( 12,r_aligned16 );
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // store vec, load low word to dst
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Load( 4, dst, am_off12, mode64 ));
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 32 );       // Reset SP
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to64:
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128HIto64:
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r_aligned16;
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     dst = newVRegI(env);
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     vec = iselVecExpr(env, e->Iex.Unop.arg);
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode *am_off0, *am_off8;
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 32 );     // Move SP down 32 bytes
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // get a quadword aligned address within our stack space
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r_aligned16 = get_sp_aligned16( env );
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off0 = PPCAMode_IR( 0, r_aligned16 );
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off8 = PPCAMode_IR( 8 ,r_aligned16 );
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // store vec, load low word (+8) or high (+0) to dst
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     PPCInstr_Load(
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        8, dst,
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op_unop == Iop_V128HIto64 ? am_off0 : am_off8,
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mode64 ));
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 32 );       // Reset SP
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_16to8:
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to8:
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32to16:
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64to8:
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* These are no-ops. */
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return iselWordExpr_R(env, e->Iex.Unop.arg);
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ReinterpF64asI64(e) */
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Given an IEEE754 double, produce an I64 with the same bit
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pattern. */
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF64asI64:
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode *am_addr;
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg r_dst  = newVRegI(env);
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );     // Move SP down 16 bytes
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // store as F64
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           fr_src, am_addr ));
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // load as Ity_I64
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );       // Reset SP
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return r_dst;
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ReinterpF32asI32(e) */
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Given an IEEE754 float, produce an I32 with the same bit
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pattern. */
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF32asI32: {
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* I believe this generates correct code for both 32- and
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            64-bit hosts. */
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_addr;
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegI(env);
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 16 );     // Move SP down 16 bytes
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // store as F32
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        fr_src, am_addr ));
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // load as Ity_I32
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( 4, r_dst, am_addr, mode64 ));
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 16 );       // Reset SP
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
1988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ReinterpD64asI64:
1990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (mode64) {
1991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            PPCAMode *am_addr;
1992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
1993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst  = newVRegI(env);
1994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            sub_from_sp( env, 16 );     // Move SP down 16 bytes
1996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
1997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            // store as D64
1999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
2000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           fr_src, am_addr ));
2001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            // load as Ity_I64
2002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
2003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            add_to_sp( env, 16 );       // Reset SP
2004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
2005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_BCDtoDPB: {
2009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCCondCode cc;
2010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt        argiregs;
2011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        argregs[1];
2012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        r_dst  = newVRegI(env);
2013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int         argreg;
2014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HWord*      fdescr;
2015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs = 0;
2017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argreg = 0;
2018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argregs[0] = hregPPC_GPR3(mode64);
2019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs |= (1 << (argreg+3));
2021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR( argregs[argreg++],
2022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     iselWordExpr_R(env, e->Iex.Unop.arg) ) );
2023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
2025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fdescr = (HWord*)h_BCDtoDPB;
2027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), argiregs ) );
2028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR(r_dst, argregs[0]));
2030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
2031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_DPBtoBCD: {
2034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCCondCode cc;
2035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt        argiregs;
2036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        argregs[1];
2037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        r_dst  = newVRegI(env);
2038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int         argreg;
2039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HWord*      fdescr;
2040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs = 0;
2042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argreg = 0;
2043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argregs[0] = hregPPC_GPR3(mode64);
2044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs |= (1 << (argreg+3));
2046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR( argregs[argreg++],
2047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     iselWordExpr_R(env, e->Iex.Unop.arg) ) );
2048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
2050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fdescr = (HWord*)h_DPBtoBCD;
2052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), argiregs ) );
2053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR(r_dst, argregs[0]));
2055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
2056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- GET --------- */
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Get: {
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8  || ty == Ity_I16 ||
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegI(env);
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          GuestStatePtr(mode64) );
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      r_dst, am_addr, mode64 ));
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_GetI: {
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* src_am
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset( env, e->Iex.GetI.descr,
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     e->Iex.GetI.ix, e->Iex.GetI.bias );
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegI(env);
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && ty == Ity_I64) {
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( toUChar(8),
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      r_dst, src_am, mode64 ));
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((!mode64) && ty == Ity_I32) {
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( toUChar(4),
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      r_dst, src_am, mode64 ));
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- CCALL --------- */
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_CCall: {
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    r_dst = newVRegI(env);
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ty == Ity_I32);
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be very restrictive for now.  Only 32/64-bit ints allowed
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for args, and 32 bits for return type. */
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.CCall.retty != Ity_I32)
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto irreducible;
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Marshal args, do the call, clear stack. */
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall( env, False, NULL,
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.CCall.cee, e->Iex.CCall.args );
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* GPR3 now holds the destination address from Pin_Goto */
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LITERAL --------- */
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32/16/8-bit literals */
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Const: {
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Long l;
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegI(env);
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRConst* con = e->Iex.Const.con;
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (con->tag) {
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U64: if (!mode64) goto irreducible;
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       l = (Long)            con->Ico.U64; break;
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:      vpanic("iselIntExpr_R.const(ppc)");
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(r_dst, (ULong)l, mode64));
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MULTIPLEX --------- */
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Mux0X: {
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((ty == Ity_I8  || ty == Ity_I16 ||
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) &&
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode  cc = mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   rX     = iselWordExpr_R(env, e->Iex.Mux0X.exprX);
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCRI* r0     = iselWordExpr_RI(env, e->Iex.Mux0X.expr0);
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_dst  = newVRegI(env);
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_tmp  = newVRegI(env);
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dst,rX));
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_tmp,
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_cond, PPCRH_Imm(False,0xFF)));
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, r_tmp, PPCRH_Imm(False,0)));
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_CMov(cc,r_dst,r0));
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (e->tag) */
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We get here if no pattern matched. */
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown irreducible:
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselIntExpr_R(ppc): cannot reduce tree");
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expression auxiliaries              ---*/
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AMODEs --------------------- */
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AMode which computes the value of the specified
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression, possibly also adding insns to the code list as a
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result.  The expression may only be a word-size one.
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool uInt_fits_in_16_bits ( UInt u )
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Is u the same as the sign-extend of its lower 16 bits? */
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i = u & 0xFFFF;
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i <<= 16;
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i >>= 16;
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(u == (UInt)i);
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool uLong_fits_in_16_bits ( ULong u )
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Is u the same as the sign-extend of its lower 16 bits? */
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long i = u & 0xFFFFULL;
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i <<= 48;
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i >>= 48;
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(u == (ULong)i);
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool uLong_is_4_aligned ( ULong u )
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool((u & 3ULL) == 0);
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AMode ( ISelEnv* env, PPCAMode* am )
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Pam_IR:
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Using uInt_fits_in_16_bits in 64-bit mode seems a bit bogus,
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         somehow, but I think it's OK. */
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return toBool( hregClass(am->Pam.IR.base) == HRcGPR(mode64) &&
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hregIsVirtual(am->Pam.IR.base) &&
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     uInt_fits_in_16_bits(am->Pam.IR.index) );
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Pam_RR:
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return toBool( hregClass(am->Pam.RR.base) == HRcGPR(mode64) &&
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hregIsVirtual(am->Pam.RR.base) &&
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hregClass(am->Pam.RR.index) == HRcGPR(mode64) &&
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hregIsVirtual(am->Pam.IR.index) );
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("sane_AMode: unknown ppc amode tag");
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPPCAMode* iselWordExpr_AMode ( ISelEnv* env, IRExpr* e, IRType xferTy )
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAMode* am = iselWordExpr_AMode_wrk(env, e, xferTy);
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sane_AMode(env, am));
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am;
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCAMode* iselWordExpr_AMode_wrk ( ISelEnv* env, IRExpr* e, IRType xferTy )
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (env->mode64) {
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the data load/store type is I32 or I64, this amode might
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         be destined for use in ld/ldu/lwa/st/stu.  In which case
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         insist that if it comes out as an _IR, the immediate must
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         have its bottom two bits be zero.  This does assume that for
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         any other type (I8/I16/I128/F32/F64/V128) the amode will not
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         be parked in any such instruction.  But that seems a
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reasonable assumption.  */
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool aligned4imm = toBool(xferTy == Ity_I32 || xferTy == Ity_I64);
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ty == Ity_I64);
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->tag == Iex_Binop
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.op == Iop_Add64
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->tag == Iex_Const
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && (aligned4imm  ? uLong_is_4_aligned(e->Iex.Binop.arg2
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                 ->Iex.Const.con->Ico.U64)
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           : True)
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && uLong_fits_in_16_bits(e->Iex.Binop.arg2
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ->Iex.Const.con->Ico.U64)) {
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             iselWordExpr_R(env, e->Iex.Binop.arg1) );
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add64(expr,expr) */
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->tag == Iex_Binop
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.op == Iop_Add64) {
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCAMode_RR( r_idx, r_base );
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ty == Ity_I32);
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->tag == Iex_Binop
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.op == Iop_Add32
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->tag == Iex_Const
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && uInt_fits_in_16_bits(e->Iex.Binop.arg2
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ->Iex.Const.con->Ico.U32)) {
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             iselWordExpr_R(env, e->Iex.Binop.arg1) );
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add32(expr,expr) */
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->tag == Iex_Binop
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Binop.op == Iop_Add32) {
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCAMode_RR( r_idx, r_base );
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't match anything in particular.  Generate it into
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a register and use that. */
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCAMode_IR( 0, iselWordExpr_R(env,e) );
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RH --------------------- */
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (reg-or-halfword-immediate).  It's important to specify whether the
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   immediate is to be regarded as signed or not.  If yes, this will
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   never return -32768 as an immediate; this guaranteed that all
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   signed immediates that are return can have their sign inverted if
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   need be. */
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH ( ISelEnv* env, Bool syned, IRExpr* e )
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRH* ri = iselWordExpr_RH_wrk(env, syned, e);
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Imm:
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ri->Prh.Imm.syned == syned);
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (syned)
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(ri->Prh.Imm.imm16 != 0x8000);
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Reg:
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregIsVirtual(ri->Prh.Reg.reg));
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("iselIntExpr_RH: unknown ppc RH tag");
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH_wrk ( ISelEnv* env, Bool syned, IRExpr* e )
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u;
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long  l;
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8  || ty == Ity_I16 ||
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRConst* con = e->Iex.Const.con;
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* What value are we aiming to generate? */
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (con->tag) {
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Note: Not sign-extending - we carry 'syned' around */
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U64: vassert(env->mode64);
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    u =              con->Ico.U64; break;
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U32: u = 0xFFFFFFFF & con->Ico.U32; break;
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U16: u = 0x0000FFFF & con->Ico.U16; break;
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U8:  u = 0x000000FF & con->Ico.U8; break;
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:      vpanic("iselIntExpr_RH.Iex_Const(ppch)");
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      l = (Long)u;
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now figure out if it's representable. */
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!syned && u <= 65535) {
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCRH_Imm(False/*unsigned*/, toUShort(u & 0xFFFF));
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (syned && l >= -32767 && l <= 32767) {
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return PPCRH_Imm(True/*signed*/, toUShort(u & 0xFFFF));
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no luck; use the Slow Way. */
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCRH_Reg( iselWordExpr_R ( env, e ) );
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RIs --------------------- */
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate an expression into an PPCRI operand.  As with
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, the expression can have type 32, 16 or 8 bits, or,
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in 64-bit mode, 64 bits. */
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRI* iselWordExpr_RI ( ISelEnv* env, IRExpr* e )
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRI* ri = iselWordExpr_RI_wrk(env, e);
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Pri_Imm:
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Pri_Reg:
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregClass(ri->Pri.Reg) == HRcGPR(env->mode64));
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregIsVirtual(ri->Pri.Reg));
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("iselIntExpr_RI: unknown ppc RI tag");
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRI* iselWordExpr_RI_wrk ( ISelEnv* env, IRExpr* e )
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long  l;
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8  || ty == Ity_I16 ||
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRConst* con = e->Iex.Const.con;
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (con->tag) {
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U64: vassert(env->mode64);
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    l = (Long)            con->Ico.U64; break;
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:      vpanic("iselIntExpr_RI.Iex_Const(ppch)");
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return PPCRI_Imm((ULong)l);
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCRI_Reg( iselWordExpr_R ( env, e ) );
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RH5u --------------------- */
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   being an immediate in the range 1 .. 31 inclusive.  Used for doing
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shift amounts.  Only used in 32-bit mode. */
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH5u ( ISelEnv* env, IRExpr* e )
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRH* ri;
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!env->mode64);
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ri = iselWordExpr_RH5u_wrk(env, e);
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Imm:
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 31);
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!ri->Prh.Imm.syned);
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Reg:
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregIsVirtual(ri->Prh.Reg.reg));
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("iselIntExpr_RH5u: unknown ppc RI tag");
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH5u_wrk ( ISelEnv* env, IRExpr* e )
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8);
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->tag == Ico_U8
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->Ico.U8 >= 1
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->Ico.U8 <= 31) {
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCRH_Reg( iselWordExpr_R ( env, e ) );
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RH6u --------------------- */
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   being an immediate in the range 1 .. 63 inclusive.  Used for doing
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shift amounts.  Only used in 64-bit mode. */
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH6u ( ISelEnv* env, IRExpr* e )
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCRH* ri;
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env->mode64);
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ri = iselWordExpr_RH6u_wrk(env, e);
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Imm:
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 63);
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!ri->Prh.Imm.syned);
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Prh_Reg:
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(hregIsVirtual(ri->Prh.Reg.reg));
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ri;
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("iselIntExpr_RH6u: unknown ppc64 RI tag");
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCRH* iselWordExpr_RH6u_wrk ( ISelEnv* env, IRExpr* e )
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8);
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->tag == Ico_U8
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->Ico.U8 >= 1
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Const.con->Ico.U8 <= 63) {
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return PPCRH_Reg( iselWordExpr_R ( env, e ) );
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- CONDCODE --------------------- */
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to evaluated a bit-typed expression, returning the
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condition code which would correspond when the expression would
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notionally have returned 1. */
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCCondCode iselCondCode ( ISelEnv* env, IRExpr* e )
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Uh, there's nothing we can sanity check here, unfortunately. */
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return iselCondCode_wrk(env,e);
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic PPCCondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Constant 1:Bit */
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True) {
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Make a compare that will always be true:
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_zero = newVRegI(env);
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(r_zero, 0, env->mode64));
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r_zero, PPCRH_Reg(r_zero)));
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Not1(...) */
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate code for the arg, and negate the test condition */
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg);
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond.test = invertCondTest(cond.test);
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return cond;
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: 32to1 or 64to1 --- */
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32to1, 64to1 */
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop &&
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       (e->Iex.Unop.op == Iop_32to1 || e->Iex.Unop.op == Iop_64to1)) {
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tmp = newVRegI(env);
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* could do better, probably -- andi. */
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Alu(Palu_AND, tmp,
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 src, PPCRH_Imm(False,1)));
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, tmp, PPCRH_Imm(False,1)));
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ8 --- */
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ8(x) */
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* could do better -- andi. */
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ8) {
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg arg = iselWordExpr_R(env, e->Iex.Unop.arg);
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tmp = newVRegI(env);
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 PPCRH_Imm(False,0xFF)));
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, tmp, PPCRH_Imm(False,0)));
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ32 --- */
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ32(x) */
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ32) {
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r1 = iselWordExpr_R(env, e->Iex.Unop.arg);
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r1, PPCRH_Imm(False,0)));
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: Cmp*32* --- */
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Cmp*32*(x,y) */
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ32
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE32
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT32S
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT32U
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE32S
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE32U)) {
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S ||
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    e->Iex.Binop.op == Iop_CmpLE32S);
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg   r1  = iselWordExpr_R(env, e->Iex.Binop.arg1);
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r1, ri2));
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNE32:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpLT32U: case Iop_CmpLT32S:
2603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
2604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpLE32U: case Iop_CmpLE32S:
2605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("iselCondCode(ppc): CmpXX32");
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ64 --- */
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ64 */
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ64) {
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!env->mode64) {
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi, lo;
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tmp = newVRegI(env);
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr( &hi, &lo, env, e->Iex.Unop.arg );
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, tmp, lo, PPCRH_Reg(hi)));
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*sign*/, True/*32bit cmp*/,
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, tmp,PPCRH_Imm(False,0)));
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {  // mode64
2624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*sign*/, False/*64bit cmp*/,
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, r_src,PPCRH_Imm(False,0)));
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: Cmp*64* --- */
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Cmp*64*(x,y) */
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ64
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE64
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT64S
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT64U
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE64S
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE64U)) {
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   syned = (e->Iex.Binop.op == Iop_CmpLT64S ||
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      e->Iex.Binop.op == Iop_CmpLE64S);
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(env->mode64);
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r1, ri2));
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNE64:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64U: return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("iselCondCode(ppc): CmpXX64");
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* var */
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_src      = lookupIRTemp(env, e->Iex.RdTmp.tmp);
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src_masked = newVRegI(env);
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env,
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               PPCInstr_Alu(Palu_AND, src_masked,
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            r_src, PPCRH_Imm(False,1)));
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env,
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            7/*cr*/, src_masked, PPCRH_Imm(False,1)));
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselCondCode(ppc): No such tag(%u)\n", e->tag);
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselCondCode(ppc)");
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (128 bit)               ---*/
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 64-bit mode ONLY: compute a 128-bit value into a register pair,
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which is returned as the first two parameters.  As with
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselWordExpr_R, these may be either real or virtual regs; in any
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case they must not be changed by subsequent code emitted by the
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   caller.  */
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt128Expr ( HReg* rHi, HReg* rLo,
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ISelEnv* env, IRExpr* e )
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env->mode64);
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselInt128Expr_wrk(rHi, rLo, env, e);
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rHi) == HRcGPR(env->mode64));
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rHi));
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rLo) == HRcGPR(env->mode64));
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rLo));
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 ISelEnv* env, IRExpr* e )
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* read 128-bit IRTemp */
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY ops --------- */
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64 x 64 -> 128 multiply */
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullU64:
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullS64: {
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg     tLo     = newVRegI(env);
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg     tHi     = newVRegI(env);
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool     syned   = toBool(e->Iex.Binop.op == Iop_MullS64);
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     False/*lo64*/, False/*64bit mul*/,
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tLo, r_srcL, r_srcR));
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_MulL(syned,
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     True/*hi64*/, False/*64bit mul*/,
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tHi, r_srcL, r_srcR));
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64HLto128(e1,e2) */
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLto128:
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- UNARY ops --------- */
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Unop) */
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselInt128Expr(ppc64): No such tag(%u)\n", e->tag);
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselInt128Expr(ppc64)");
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (64 bit)                ---*/
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 32-bit mode ONLY: compute a 128-bit value into a register quad */
2766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr_to_32x4 ( HReg* rHi, HReg* rMedHi, HReg* rMedLo,
2767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                     HReg* rLo, ISelEnv* env, IRExpr* e )
2768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(!env->mode64);
2770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselInt128Expr_to_32x4_wrk(rHi, rMedHi, rMedLo, rLo, env, e);
2771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  if 0
2772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  endif
2774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rHi) == HRcInt32);
2775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rHi));
2776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rMedHi) == HRcInt32);
2777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rMedHi));
2778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rMedLo) == HRcInt32);
2779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rMedLo));
2780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rLo) == HRcInt32);
2781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rLo));
2782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr_to_32x4_wrk ( HReg* rHi, HReg* rMedHi,
2785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         HReg* rMedLo, HReg* rLo,
2786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         ISelEnv* env, IRExpr* e )
2787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(e);
2789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
2790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* read 128-bit IRTemp */
2792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_RdTmp) {
2793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      lookupIRTempQuad( rHi, rMedHi, rMedLo, rLo, env, e->Iex.RdTmp.tmp);
2794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
2795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Binop) {
2798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IROp op_binop = e->Iex.Binop.op;
2800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (op_binop) {
2801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_64HLto128:
2802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselInt64Expr(rHi, rMedHi, env, e->Iex.Binop.arg1);
2803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselInt64Expr(rMedLo, rLo, env, e->Iex.Binop.arg2);
2804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
2805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
2806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("iselInt128Expr_to_32x4_wrk: Binop case 0x%x not found\n",
2807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    op_binop);
2808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
2809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("iselInt128Expr_to_32x4_wrk: e->tag 0x%x not found\n", e->tag);
2813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return;
2814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32-bit mode ONLY: compute a 64-bit value into a register pair,
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which is returned as the first two parameters.  As with
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, these may be either real or virtual regs; in any
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case they must not be changed by subsequent code emitted by the
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   caller.  */
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr ( HReg* rHi, HReg* rLo,
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            ISelEnv* env, IRExpr* e )
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(!env->mode64);
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselInt64Expr_wrk(rHi, rLo, env, e);
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rHi) == HRcInt32);
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rHi));
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rLo) == HRcInt32);
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rLo));
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ISelEnv* env, IRExpr* e )
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit load */
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo    = newVRegI(env);
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi    = newVRegI(env);
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!env->mode64);
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( 4/*byte-load*/,
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   tHi, PPCAMode_IR( 0, r_addr ),
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   False/*32-bit insn please*/) );
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( 4/*byte-load*/,
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   tLo, PPCAMode_IR( 4, r_addr ),
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   False/*32-bit insn please*/) );
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit literal */
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong w64 = e->Iex.Const.con->Ico.U64;
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  wLo = ((UInt)w64) & 0xFFFFFFFF;
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg  tLo = newVRegI(env);
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg  tHi = newVRegI(env);
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_U64);
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(tHi, (Long)(Int)wHi, False/*mode32*/));
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_LI(tLo, (Long)(Int)wLo, False/*mode32*/));
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* read 64-bit IRTemp */
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit GET */
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       GuestStatePtr(False/*mode32*/) );
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr4 = advance4(env, am_addr);
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( 4, tHi, am_addr,  False/*mode32*/ ));
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Load( 4, tLo, am_addr4, False/*mode32*/ ));
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit Mux0X */
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg e0Lo, e0Hi, eXLo, eXHi;
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCCondCode cc = mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_tmp  = newVRegI(env);
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0);
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr(&eXHi, &eXLo, env, e->Iex.Mux0X.exprX);
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVds_RR(tHi,eXHi));
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVds_RR(tLo,eXLo));
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Alu(Palu_AND,
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 r_tmp, r_cond, PPCRH_Imm(False,0xFF)));
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 7/*cr*/, r_tmp, PPCRH_Imm(False,0)));
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_CMov(cc,tHi,PPCRI_Reg(e0Hi)));
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_CMov(cc,tLo,PPCRI_Reg(e0Lo)));
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY ops --------- */
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp op_binop = e->Iex.Binop.op;
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (op_binop) {
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 32 x 32 -> 64 multiply */
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MullU32:
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MullS32: {
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     tLo     = newVRegI(env);
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     tHi     = newVRegI(env);
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool     syned   = toBool(op_binop == Iop_MullS32);
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        False/*lo32*/, True/*32bit mul*/,
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        tLo, r_srcL, r_srcR));
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_MulL(syned,
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        True/*hi32*/, True/*32bit mul*/,
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        tHi, r_srcL, r_srcR));
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Or64/And64/Xor64 */
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Or64:
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_And64:
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Xor64: {
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xLo, xHi, yLo, yHi;
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAluOp op = (op_binop == Iop_Or64) ? Palu_OR :
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          (op_binop == Iop_And64) ? Palu_AND : Palu_XOR;
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Alu(op, tHi, xHi, PPCRH_Reg(yHi)));
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Alu(op, tLo, xLo, PPCRH_Reg(yLo)));
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Add64 */
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add64: {
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xLo, xHi, yLo, yHi;
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AddSubC( True/*add*/, True /*set carry*/,
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            tLo, xLo, yLo));
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AddSubC( True/*add*/, False/*read carry*/,
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            tHi, xHi, yHi));
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 32HLto64(e1,e2) */
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32HLto64:
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* F64toI64[S|U] */
2986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_F64toI64S: case Iop_F64toI64U: {
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      tLo     = newVRegI(env);
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      tHi     = newVRegI(env);
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      r1      = StackFramePtr(env->mode64);
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2);
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      ftmp    = newVRegF(env);
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(!env->mode64);
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Set host rounding mode */
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
3001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          (op_binop == Iop_F64toI64S) ? True : False,
3002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          True, ftmp, fsrc));
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ///* Restore default FPU rounding. */
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //set_FPU_rounding_default( env );
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- UNARY ops --------- */
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CmpwNEZ64(e) */
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpwNEZ64: {
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argHi, argLo;
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tmp1  = newVRegI(env);
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tmp2  = newVRegI(env);
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg);
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* tmp1 = argHi | argLo */
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, tmp1, argHi, PPCRH_Reg(argLo)));
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* tmp2 = (tmp1 | -tmp1) >>s 31 */
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Unary(Pun_NEG,tmp2,tmp1));
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, tmp2, tmp2, PPCRH_Reg(tmp1)));
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tmp2, tmp2, PPCRH_Imm(False, 31)));
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tmp2;
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tmp2; /* yes, really tmp2 */
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Left64 */
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Left64: {
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argHi, argLo;
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg zero32 = newVRegI(env);
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg resHi  = newVRegI(env);
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg resLo  = newVRegI(env);
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg);
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(env->mode64 == False);
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(zero32, 0, env->mode64));
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* resHi:resLo = - argHi:argLo */
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AddSubC( False/*sub*/, True/*set carry*/,
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         resLo, zero32, argLo ));
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AddSubC( False/*sub*/, False/*read carry*/,
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         resHi, zero32, argHi ));
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* resHi:resLo |= srcHi:srcLo */
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, resLo, resLo, PPCRH_Reg(argLo)));
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_OR, resHi, resHi, PPCRH_Reg(argHi)));
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = resHi;
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = resLo;
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Sto64(e) */
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Sto64: {
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi = newVRegI(env);
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tHi, src, PPCRH_Imm(False,31)));
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = src;
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 32Uto64(e) */
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32Uto64: {
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi = newVRegI(env);
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tLo = iselWordExpr_R(env, e->Iex.Unop.arg);
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(tHi, 0, False/*mode32*/));
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_128to64: {
3087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Narrow, return the low 64-bit half as a 32-bit
3088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          * register pair */
3089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_Hi    = INVALID_HREG;
3090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_MedHi = INVALID_HREG;
3091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_MedLo = INVALID_HREG;
3092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_Lo    = INVALID_HREG;
3093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
3095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                env, e->Iex.Unop.arg);
3096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = r_MedLo;
3097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = r_Lo;
3098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_128HIto64: {
3102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Narrow, return the high 64-bit half as a 32-bit
3103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          *  register pair */
3104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_Hi    = INVALID_HREG;
3105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_MedHi = INVALID_HREG;
3106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_MedLo = INVALID_HREG;
3107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_Lo    = INVALID_HREG;
3108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
3110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                env, e->Iex.Unop.arg);
3111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = r_Hi;
3112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = r_MedHi;
3113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* V128{HI}to64 */
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128HIto64:
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_V128to64: {
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_aligned16;
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int  off = e->Iex.Unop.op==Iop_V128HIto64 ? 0 : 8;
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tLo = newVRegI(env);
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi = newVRegI(env);
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg vec = iselVecExpr(env, e->Iex.Unop.arg);
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_off0, *am_offLO, *am_offHI;
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 32 );     // Move SP down 32 bytes
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // get a quadword aligned address within our stack space
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_aligned16 = get_sp_aligned16( env );
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off0  = PPCAMode_IR( 0,     r_aligned16 );
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_offHI = PPCAMode_IR( off,   r_aligned16 );
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_offLO = PPCAMode_IR( off+4, r_aligned16 );
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // store as Vec128
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // load hi,lo words (of hi/lo half of vec) as Ity_I32's
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Load( 4, tHi, am_offHI, False/*mode32*/ ));
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_Load( 4, tLo, am_offLO, False/*mode32*/ ));
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 32 );       // Reset SP
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* could do better than this, but for now ... */
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_1Sto64: {
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tLo = newVRegI(env);
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tHi = newVRegI(env);
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg);
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Set(cond,tLo));
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tLo, tLo, PPCRH_Imm(False,31)));
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     tLo, tLo, PPCRH_Imm(False,31)));
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(tHi, tLo));
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Not64: {
3166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg xLo, xHi;
3167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg tmpLo = newVRegI(env);
3168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg tmpHi = newVRegI(env);
3169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg);
3170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Unary(Pun_NOT,tmpLo,xLo));
3171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Unary(Pun_NOT,tmpHi,xHi));
3172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *rHi = tmpHi;
3173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *rLo = tmpLo;
3174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return;
3175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
3176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ReinterpF64asI64(e) */
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Given an IEEE754 double, produce an I64 with the same bit
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pattern. */
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ReinterpF64asI64: {
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_addr0, *am_addr1;
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src  = iselDblExpr(env, e->Iex.Unop.arg);
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dstLo = newVRegI(env);
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dstHi = newVRegI(env);
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 16 );     // Move SP down 16 bytes
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // store as F64
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        fr_src, am_addr0 ));
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // load hi,lo as Ity_I32's
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( 4, r_dstHi,
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      am_addr0, False/*mode32*/ ));
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Load( 4, r_dstLo,
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      am_addr1, False/*mode32*/ ));
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = r_dstHi;
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = r_dstLo;
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 16 );       // Reset SP
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ReinterpD64asI64: {
3207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_src  = iselDfp64Expr(env, e->Iex.Unop.arg);
3208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCAMode *am_addr0, *am_addr1;
3209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstLo = newVRegI(env);
3210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstHi = newVRegI(env);
3211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         sub_from_sp( env, 16 );     // Move SP down 16 bytes
3214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
3215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
3216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // store as D64
3218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
3219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        fr_src, am_addr0 ));
3220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // load hi,lo as Ity_I32's
3222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Load( 4, r_dstHi,
3223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      am_addr0, False/*mode32*/ ));
3224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Load( 4, r_dstLo,
3225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      am_addr1, False/*mode32*/ ));
3226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = r_dstHi;
3227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = r_dstLo;
3228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         add_to_sp( env, 16 );       // Reset SP
3230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_BCDtoDPB: {
3235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCCondCode cc;
3236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt        argiregs;
3237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        argregs[2];
3238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int         argreg;
3239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        tLo = newVRegI(env);
3240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        tHi = newVRegI(env);
3241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        tmpHi;
3242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        tmpLo;
3243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ULong       target;
3244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool        mode64 = env->mode64;
3245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argregs[0] = hregPPC_GPR3(mode64);
3247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argregs[1] = hregPPC_GPR4(mode64);
3248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs = 0;
3250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argreg = 0;
3251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselInt64Expr( &tmpHi, &tmpLo, env, e->Iex.Unop.arg );
3253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs |= ( 1 << (argreg+3 ) );
3255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, mk_iMOVds_RR( argregs[argreg++], tmpHi ) );
3256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs |= ( 1 << (argreg+3 ) );
3258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, mk_iMOVds_RR( argregs[argreg], tmpLo ) );
3259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
3261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         target = toUInt( Ptr_to_ULong(h_BCDtoDPB ) );
3262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, PPCInstr_Call( cc, (Addr64)target, argiregs ) );
3264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, mk_iMOVds_RR( tHi, argregs[argreg-1] ) );
3265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, mk_iMOVds_RR( tLo, argregs[argreg] ) );
3266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = tHi;
3268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = tLo;
3269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_DPBtoBCD: {
3273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCCondCode cc;
3274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UInt        argiregs;
3275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        argregs[2];
3276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Int         argreg;
3277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        tLo = newVRegI(env);
3278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        tHi = newVRegI(env);
3279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        tmpHi;
3280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        tmpLo;
3281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ULong       target;
3282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool        mode64 = env->mode64;
3283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argregs[0] = hregPPC_GPR3(mode64);
3285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argregs[1] = hregPPC_GPR4(mode64);
3286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs = 0;
3288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argreg = 0;
3289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg);
3291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs |= (1 << (argreg+3));
3293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR( argregs[argreg++], tmpHi ));
3294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs |= (1 << (argreg+3));
3296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR( argregs[argreg], tmpLo));
3297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
3299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         target = toUInt( Ptr_to_ULong( h_DPBtoBCD ) );
3301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs ) );
3303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR(tHi, argregs[argreg-1]));
3304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR(tLo, argregs[argreg]));
3305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = tHi;
3307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = tLo;
3308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Unop) */
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselInt64Expr(ppc): No such tag(%u)\n", e->tag);
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselInt64Expr(ppc)");
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (32 bit)         ---*/
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Nothing interesting here; really just wrappers for
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit stuff. */
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselFltExpr_wrk( env, e );
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool        mode64 = env->mode64;
3344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_F32);
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr;
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegF(env);
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_F32);
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F32/*xfer*/);
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegF(env);
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       GuestStatePtr(env->mode64) );
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4, r_dst, am_addr ));
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is quite subtle.  The only way to do the relevant
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         truncation is to do a single-precision store and then a
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         double precision load to get it back into a register.  The
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         problem is, if the data is then written to memory a second
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         time, as in
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            STbe(...) = TruncF64asF32(...)
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         then will the second truncation further alter the value?  The
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         answer is no: flds (as generated here) followed by fsts
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (generated for the STbe) is the identity function on 32-bit
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         floats, so we are safe.
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Another upshot of this is that if iselStmt can see the
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         entirety of
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            STbe(...) = TruncF64asF32(arg)
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         then it can short circuit having to deal with TruncF64asF32
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         individually; instead just compute arg into a 64-bit FP
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         register and do 'fsts' (since that itself does the
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         truncation).
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         We generate pretty poor code here (should be ok both for
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         32-bit and 64-bit mode); but it is expected that for the most
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         part the latter optimisation will apply and hence this code
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         will not often be used.
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      fsrc    = iselDblExpr(env, e->Iex.Unop.arg);
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      fdst    = newVRegF(env);
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sub_from_sp( env, 16 );
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // store as F32, hence truncating
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     fsrc, zero_r1 ));
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // and reload.  Good huh?! (sigh)
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4,
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     fdst, zero_r1 ));
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_sp( env, 16 );
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return fdst;
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64UtoF32) {
3414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (mode64) {
3415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg fdst = newVRegF(env);
3416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2);
3417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg r1   = StackFramePtr(env->mode64);
3418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Set host rounding mode */
3421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         sub_from_sp( env, 16 );
3424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
3426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       False, False,
3429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       fdst, fdst));
3430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         add_to_sp( env, 16 );
3432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ///* Restore default FPU rounding. */
3434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //set_FPU_rounding_default( env );
3435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return fdst;
3436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
3437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* 32-bit mode */
3438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg fdst = newVRegF(env);
3439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg isrcHi, isrcLo;
3440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg r1   = StackFramePtr(env->mode64);
3441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2);
3445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Set host rounding mode */
3447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         sub_from_sp( env, 16 );
3450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
3452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
3453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       False, False,
3456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       fdst, fdst));
3457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         add_to_sp( env, 16 );
3459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ///* Restore default FPU rounding. */
3461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //set_FPU_rounding_default( env );
3462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return fdst;
3463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
3464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
3466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselFltExpr(ppc): No such tag(%u)\n", e->tag);
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselFltExpr_wrk(ppc)");
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (64 bit)         ---*/
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit floating point value into a register, the identity
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of which is returned.  As with iselIntExpr_R, the reg may be either
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   real or virtual; in any case it must not be changed by subsequent
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code emitted by the caller.  */
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IEEE 754 formats.  From http://www.freesoft.org/CIE/RFC/1832/32.htm:
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Type                  S (1 bit)   E (11 bits)   F (52 bits)
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ----                  ---------   -----------   -----------
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    signalling NaN        u           2047 (max)    .0uuuuu---u
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    (with at least
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     one 1 bit)
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    quiet NaN             u           2047 (max)    .1uuuuu---u
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    negative infinity     1           2047 (max)    .000000---0
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    positive infinity     0           2047 (max)    .000000---0
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    negative zero         1           0             .000000---0
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    positive zero         0           0             .000000---0
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselDblExpr_wrk( env, e );
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcFlt64);
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_F64);
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LITERAL --------- */
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union { UInt u32x2[2]; ULong u64; Double f64; } u;
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u) == 8);
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.u64) == 8);
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.f64) == 8);
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.u32x2) == 8);
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Const.con->tag == Ico_F64) {
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u.f64 = e->Iex.Const.con->Ico.F64;
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (e->Iex.Const.con->tag == Ico_F64i) {
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u.u64 = e->Iex.Const.con->Ico.F64i;
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselDblExpr(ppc): const");
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64) {
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcHi = newVRegI(env);
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcLo = newVRegI(env);
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(r_srcHi, u.u32x2[0], mode64));
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(r_srcLo, u.u32x2[1], mode64));
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else { // mode64
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = newVRegI(env);
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(r_src, u.u64, mode64));
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LOAD --------- */
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegF(env);
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr;
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_F64);
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F64/*xfer*/);
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- GET --------- */
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r_dst = newVRegF(env);
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       GuestStatePtr(mode64) );
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ));
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r_dst;
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- OPS --------- */
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Qop) {
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCFpOp fpop = Pfp_INVALID;
3575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Qop.details->op) {
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MAddF64:    fpop = Pfp_MADDD; break;
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MAddF64r32: fpop = Pfp_MADDS; break;
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MSubF64:    fpop = Pfp_MSUBD; break;
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MSubF64r32: fpop = Pfp_MSUBS; break;
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Pfp_INVALID) {
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegF(env);
3584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcML  = iselDblExpr(env, e->Iex.Qop.details->arg2);
3585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcMR  = iselDblExpr(env, e->Iex.Qop.details->arg3);
3586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcAcc = iselDblExpr(env, e->Iex.Qop.details->arg4);
3587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         set_FPU_rounding_mode( env, e->Iex.Qop.details->arg1 );
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpMulAcc(fpop, r_dst,
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               r_srcML, r_srcMR, r_srcAcc));
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Triop) {
3595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTriop *triop = e->Iex.Triop.details;
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCFpOp fpop = Pfp_INVALID;
3597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (triop->op) {
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AddF64:    fpop = Pfp_ADDD; break;
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SubF64:    fpop = Pfp_SUBD; break;
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulF64:    fpop = Pfp_MULD; break;
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivF64:    fpop = Pfp_DIVD; break;
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AddF64r32: fpop = Pfp_ADDS; break;
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SubF64r32: fpop = Pfp_SUBS; break;
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulF64r32: fpop = Pfp_MULS; break;
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivF64r32: fpop = Pfp_DIVS; break;
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Pfp_INVALID) {
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = newVRegF(env);
3610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcL = iselDblExpr(env, triop->arg2);
3611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcR = iselDblExpr(env, triop->arg3);
3612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         set_FPU_rounding_mode( env, triop->arg1 );
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpBinary(fpop, r_dst, r_srcL, r_srcR));
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (triop->op) {
3617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_QuantizeD64:          fpop = Pfp_DQUA;  break;
3618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SignificanceRoundD64: fpop = Pfp_RRDTR; break;
3619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: break;
3620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fpop != Pfp_INVALID) {
3622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dst = newVRegF(env);
3623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcL = iselDblExpr(env, triop->arg2);
3624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcR = iselDblExpr(env, triop->arg3);
3625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1);
3626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // will set TE and RMC when issuing instruction
3628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR, rmc));
3629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
3630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCFpOp fpop = Pfp_INVALID;
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
3636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SqrtF64:   fpop = Pfp_SQRT;   break;
3637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_I64StoD64: fpop = Pfp_DCFFIX; break;
3638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D64toI64S: fpop = Pfp_DCTFIX; break;
3639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: break;
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Pfp_INVALID) {
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = newVRegF(env);
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, e->Iex.Binop.arg2);
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fr_dst;
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_RoundF64toF32) {
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = newVRegF(env);
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselDblExpr(env, e->Iex.Binop.arg2);
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpRSP(r_dst, r_src));
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         //set_FPU_rounding_default( env );
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r_dst;
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (e->Iex.Binop.op == Iop_I64StoF64 || e->Iex.Binop.op == Iop_I64UtoF64) {
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg fdst = newVRegF(env);
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2);
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg r1   = StackFramePtr(env->mode64);
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Set host rounding mode */
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          e->Iex.Binop.op == Iop_I64StoF64,
3677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          True/*fdst is 64 bit*/,
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          fdst, fdst));
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ///* Restore default FPU rounding. */
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //set_FPU_rounding_default( env );
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return fdst;
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* 32-bit mode */
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg fdst = newVRegF(env);
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg isrcHi, isrcLo;
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg r1   = StackFramePtr(env->mode64);
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2);
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Set host rounding mode */
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 16 );
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          e->Iex.Binop.op == Iop_I64StoF64,
3705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          True/*fdst is 64 bit*/,
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          fdst, fdst));
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 16 );
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ///* Restore default FPU rounding. */
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //set_FPU_rounding_default( env );
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return fdst;
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCFpOp fpop = Pfp_INVALID;
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_NegF64:     fpop = Pfp_NEG; break;
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AbsF64:     fpop = Pfp_ABS; break;
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Est5FRSqrt: fpop = Pfp_RSQRTE; break;
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_RoundF64toF64_NegINF:  fpop = Pfp_FRIM; break;
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_RoundF64toF64_PosINF:  fpop = Pfp_FRIP; break;
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_RoundF64toF64_NEAREST: fpop = Pfp_FRIN; break;
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_RoundF64toF64_ZERO:    fpop = Pfp_FRIZ; break;
3728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_ExtractExpD64:         fpop = Pfp_DXEX; break;
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Pfp_INVALID) {
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = newVRegF(env);
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fr_dst;
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ReinterpI64asF64: {
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Given an I64, produce an IEEE754 double with the same
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               bit pattern. */
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!mode64) {
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg r_srcHi, r_srcLo;
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return mk_LoadR64toFPR( env, r_src );
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_F32toF64: {
3755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (e->Iex.Unop.arg->tag == Iex_Unop &&
3756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     e->Iex.Unop.arg->Iex.Unop.op == Iop_ReinterpI32asF32 ) {
3757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               e = e->Iex.Unop.arg;
3758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
3760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               HReg fr_dst = newVRegF(env);
3761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               PPCAMode *am_addr;
3762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               sub_from_sp( env, 16 );        // Move SP down 16 bytes
3764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               am_addr = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               // store src as Ity_I32's
3767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               addInstr(env, PPCInstr_Store( 4, am_addr, src, env->mode64 ));
3768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               // load single precision float, but the end results loads into a
3770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               // 64-bit FP register -- i.e., F64.
3771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, fr_dst, am_addr));
3772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               add_to_sp( env, 16 );          // Reset SP
3774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               return fr_dst;
3775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
3776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* this is a no-op */
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg res = iselFltExpr(env, e->Iex.Unop.arg);
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return res;
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MULTIPLEX --------- */
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cc = mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_cond = iselWordExpr_R(env, e->Iex.Mux0X.cond);
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg frX    = iselDblExpr(env, e->Iex.Mux0X.exprX);
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr0    = iselDblExpr(env, e->Iex.Mux0X.expr0);
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = newVRegF(env);
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_tmp  = newVRegI(env);
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Alu(Palu_AND, r_tmp,
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    r_cond, PPCRH_Imm(False,0xFF)));
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary( Pfp_MOV, fr_dst, frX ));
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    7/*cr*/, r_tmp, PPCRH_Imm(False,0)));
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpCMov( cc, fr_dst, fr0 ));
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return fr_dst;
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselDblExpr(ppc): No such tag(%u)\n", e->tag);
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselDblExpr_wrk(ppc)");
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselDfp64Expr(ISelEnv* env, IRExpr* e)
3813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg r = iselDfp64Expr_wrk( env, e );
3815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(r) == HRcFlt64);
3816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert( hregIsVirtual(r) );
3817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return r;
3818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY */
3821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e)
3822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool mode64 = env->mode64;
3824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty = typeOfIRExpr( env->type_env, e );
3825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg r_dstHi, r_dstLo;
3826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert( e );
3828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert( ty == Ity_D64 );
3829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_RdTmp) {
3831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return lookupIRTemp( env, e->Iex.RdTmp.tmp );
3832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------- GET --------- */
3835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Get) {
3836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dst = newVRegF( env );
3837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       GuestStatePtr(mode64) );
3839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
3840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return r_dst;
3841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------- OPS --------- */
3844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Qop) {
3845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dst = newVRegF( env );
3846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return r_dst;
3847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Unop) {
3850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg fr_dst = newVRegF(env);
3851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Unop.op) {
3852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ReinterpI64asD64: {
3853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Given an I64, produce an IEEE754 DFP with the same
3854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               bit pattern. */
3855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!mode64) {
3856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcHi, r_srcLo;
3857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
3858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
3859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
3860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return mk_LoadR64toFPR( env, r_src );
3862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ExtractExpD64: {
3866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
3867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Dfp64Unary(Pfp_DXEX, fr_dst, fr_src));
3869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ExtractExpD128: {
3872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Result is a D64 */
3873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcHi;
3874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcLo;
3875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
3877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_ExtractExpD128(Pfp_DXEXQ, fr_dst,
3878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng					       r_srcHi, r_srcLo));
3879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D32toD64: {
3882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
3883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
3884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D128HItoD64:
3887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg );
3888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dstHi;
3889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D128LOtoD64:
3890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg );
3891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dstLo;
3892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_InsertExpD64: {
3893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
3894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
3895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Dfp64Binary(Pfp_DIEX, fr_dst, fr_srcL,
3897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng					    fr_srcR));
3898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       }
3900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
3901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf( "ERROR: iselDfp64Expr_wrk, UNKNOWN unop case %d\n",
3902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     e->Iex.Unop.op );
3903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Binop) {
3907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Binop.op) {
3909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D128toI64S: {
3910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCFpOp fpop = Pfp_DCTFIXQ;
3911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_dst  = newVRegF(env);
3912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcHi = newVRegF(env);
3913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcLo = newVRegF(env);
3914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
3916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
3917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
3918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D128toD64: {
3921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCFpOp fpop = Pfp_DRDPQ;
3922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_dst  = newVRegF(env);
3923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcHi = newVRegF(env);
3924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcLo = newVRegF(env);
3925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
3927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
3928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
3929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
3932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
3933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (e->Iex.Unop.op == Iop_RoundD64toInt) {
3937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_dst = newVRegF(env);
3938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_src = newVRegF(env);
3939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1);
3940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
3942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpRound(fr_dst, fr_src, r_rmc));
3943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Binop) {
3948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      PPCFpOp fpop = Pfp_INVALID;
3949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg fr_dst = newVRegF(env);
3950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Binop.op) {
3952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D64toD32:     fpop = Pfp_DRSP;   break;
3953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_I64StoD64:    fpop = Pfp_DCFFIX; break;
3954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D64toI64S:    fpop = Pfp_DCTFIX; break;
3955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: break;
3956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fpop != Pfp_INVALID) {
3958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
3959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
3960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
3961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Binop.op) {
3965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* shift instructions F64, I32 -> F64 */
3966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlD64: fpop = Pfp_DSCLI; break;
3967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrD64: fpop = Pfp_DSCRI; break;
3968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: break;
3969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fpop != Pfp_INVALID) {
3971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg1);
3972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2);
3973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpShift(fpop, fr_dst, fr_src, shift));
3975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Binop.op) {
3979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_InsertExpD64:
3980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DIEX;
3981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: 	break;
3983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fpop != Pfp_INVALID) {
3985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_srcL = iselDfp64Expr(env, e->Iex.Binop.arg1);
3986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2);
3987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Dfp64Binary(fpop, fr_dst, fr_srcL, fr_srcR));
3988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return fr_dst;
3989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Triop) {
3993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTriop *triop = e->Iex.Triop.details;
3994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      PPCFpOp fpop = Pfp_INVALID;
3995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (triop->op) {
3997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_AddD64:
3998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DFPADD;
3999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SubD64:
4001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DFPSUB;
4002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_MulD64:
4004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DFPMUL;
4005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_DivD64:
4007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DFPDIV;
4008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
4010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fpop != Pfp_INVALID) {
4013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dst = newVRegF( env );
4014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcL = iselDfp64Expr( env, triop->arg2 );
4015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcR = iselDfp64Expr( env, triop->arg3 );
4016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         set_FPU_DFP_rounding_mode( env, triop->arg1 );
4018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, PPCInstr_Dfp64Binary( fpop, r_dst, r_srcL, r_srcR ) );
4019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
4020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (triop->op) {
4023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_QuantizeD64:          fpop = Pfp_DQUA;  break;
4024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SignificanceRoundD64: fpop = Pfp_RRDTR; break;
4025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: break;
4026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fpop != Pfp_INVALID) {
4028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dst = newVRegF(env);
4029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcL = iselDfp64Expr(env, triop->arg2);
4030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcR = iselDfp64Expr(env, triop->arg3);
4031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1);
4032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR,
4034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            rmc));
4035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
4036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr( e );
4040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vpanic( "iselDfp64Expr_wrk(ppc)" );
4041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
4042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDfp128Expr(HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e)
4044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
4045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselDfp128Expr_wrk( rHi, rLo, env, e );
4046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert( hregIsVirtual(*rHi) );
4047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert( hregIsVirtual(*rLo) );
4048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
4049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY */
4051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDfp128Expr_wrk(HReg* rHi, HReg *rLo, ISelEnv* env, IRExpr* e)
4052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
4053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert( e );
4054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert( typeOfIRExpr(env->type_env,e) == Ity_D128 );
4055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* read 128-bit IRTemp */
4057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_RdTmp) {
4058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp );
4059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
4060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Unop) {
4063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      PPCFpOp fpop = Pfp_INVALID;
4064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dstHi = newVRegF(env);
4065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dstLo = newVRegF(env);
4066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (e->Iex.Unop.op == Iop_I64StoD128) {
4068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_src   = iselDfp64Expr(env, e->Iex.Unop.arg);
4069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DCFFIXQ;
4070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpI64StoD128(fpop, r_dstHi, r_dstLo,
4072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              r_src));
4073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (e->Iex.Unop.op == Iop_D64toD128) {
4075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_src   = iselDfp64Expr(env, e->Iex.Unop.arg);
4076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DCTQPQ;
4077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Source is 64bit result is 128 bit.  High 64bit source arg,
4079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          * is ignored by the instruction.  Set high arg to r_src just
4080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          * to meet the vassert tests.
4081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          */
4082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_Dfp128Unary(fpop, r_dstHi, r_dstLo,
4083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            r_src, r_src));
4084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rHi = r_dstHi;
4086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rLo = r_dstLo;
4087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
4088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------- OPS --------- */
4091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Binop) {
4092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_srcHi;
4093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_srcLo;
4094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Binop.op) {
4096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D64HLtoD128:
4097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         r_srcHi = iselDfp64Expr( env, e->Iex.Binop.arg1 );
4098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         r_srcLo = iselDfp64Expr( env, e->Iex.Binop.arg2 );
4099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = r_srcHi;
4100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = r_srcLo;
4101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_D128toD64: {
4104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCFpOp fpop = Pfp_DRDPQ;
4105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_dst  = newVRegF(env);
4106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
4108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
4109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
4110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Need to meet the interface spec but the result is
4112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          * just 64-bits so send the result back in both halfs.
4113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          */
4114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = fr_dst;
4115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = fr_dst;
4116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShlD128:
4119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ShrD128: {
4120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_dst_hi = newVRegF(env);
4121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_dst_lo = newVRegF(env);
4122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2);
4123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCFpOp fpop = Pfp_DSCLIQ;  /* fix later if necessary */
4124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1);
4126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_ShrD128)
4128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fpop = Pfp_DSCRIQ;
4129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpShift128(fpop, fr_dst_hi, fr_dst_lo,
4131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            r_srcHi, r_srcLo, shift));
4132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = fr_dst_hi;
4134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = fr_dst_lo;
4135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_RoundD128toInt: {
4138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstHi = newVRegF(env);
4139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstLo = newVRegF(env);
4140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1);
4141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // will set R and RMC when issuing instruction
4143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
4144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpRound128(r_dstHi, r_dstLo,
4146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            r_srcHi, r_srcLo, r_rmc));
4147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = r_dstHi;
4148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = r_dstLo;
4149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_InsertExpD128: {
4152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstHi = newVRegF(env);
4153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstLo = newVRegF(env);
4154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcL  = newVRegF(env);
4155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         r_srcL = iselDfp64Expr(env, e->Iex.Binop.arg1);
4157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
4158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_InsertExpD128(Pfp_DIEXQ,
4159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              r_dstHi, r_dstLo,
4160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              r_srcL, r_srcHi, r_srcLo));
4161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = r_dstHi;
4162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = r_dstLo;
4163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
4166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf( "ERROR: iselDfp128Expr_wrk, UNKNOWN binop case %d\n",
4167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     e->Iex.Binop.op );
4168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Triop) {
4173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTriop *triop = e->Iex.Triop.details;
4174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      PPCFpOp fpop = Pfp_INVALID;
4175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (triop->op) {
4176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_AddD128:
4177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DFPADDQ;
4178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SubD128:
4180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DFPSUBQ;
4181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_MulD128:
4183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DFPMULQ;
4184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_DivD128:
4186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fpop = Pfp_DFPDIVQ;
4187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
4189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fpop != Pfp_INVALID) {
4193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstHi = newVRegV( env );
4194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstLo = newVRegV( env );
4195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcRHi = newVRegV( env );
4196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcRLo = newVRegV( env );
4197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* dst will be used to pass in the left operand and get the result. */
4199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr( &r_dstHi, &r_dstLo, env, triop->arg2 );
4200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr( &r_srcRHi, &r_srcRLo, env, triop->arg3 );
4201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         set_FPU_rounding_mode( env, triop->arg1 );
4202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env,
4203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   PPCInstr_Dfp128Binary( fpop, r_dstHi, r_dstLo,
4204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          r_srcRHi, r_srcRLo ) );
4205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = r_dstHi;
4206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = r_dstLo;
4207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (triop->op) {
4210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_QuantizeD128:          fpop = Pfp_DQUAQ;  break;
4211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_SignificanceRoundD128: fpop = Pfp_DRRNDQ; break;
4212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default: break;
4213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fpop != Pfp_INVALID) {
4215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstHi = newVRegF(env);
4216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstLo = newVRegF(env);
4217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcHi = newVRegF(env);
4218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcLo = newVRegF(env);
4219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCRI* rmc = iselWordExpr_RI(env, triop->arg1);
4220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* dst will be used to pass in the left operand and get the result */
4222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr(&r_dstHi, &r_dstLo, env, triop->arg2);
4223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr(&r_srcHi, &r_srcLo, env, triop->arg3);
4224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // will set RMC when issuing instruction
4226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
4227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               r_srcHi, r_srcLo, rmc));
4228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = r_dstHi;
4229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = r_dstLo;
4230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr( e );
4235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vpanic( "iselDfp128Expr(ppc64)" );
4236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
4237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: SIMD (Vector) expressions, 128 bit.         ---*/
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr ( ISelEnv* env, IRExpr* e )
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselVecExpr_wrk( env, e );
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcVec128);
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PPCAvOp op = Pav_INVALID;
4259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   PPCAvFpOp fpop = Pavfp_INVALID;
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty = typeOfIRExpr(env->type_env,e);
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_V128);
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Guest state vectors are 16byte aligned,
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         so don't need to worry here */
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env,
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               PPCInstr_AvLdSt( True/*load*/, 16, dst,
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                PPCAMode_IR( e->Iex.Get.offset,
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             GuestStatePtr(mode64) )));
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* am_addr;
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg v_dst = newVRegV(env);
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_V128);
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_V128/*xfer*/);
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, v_dst, am_addr));
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return v_dst;
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NotV128: {
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, arg));
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ8x16: {
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg zero = newVRegV(env);
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin8x16(Pav_CMPEQU, dst, arg, zero));
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ16x8: {
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg zero = newVRegV(env);
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin16x8(Pav_CMPEQU, dst, arg, zero));
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ32x4: {
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg zero = newVRegV(env);
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, dst, arg, zero));
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Recip32Fx4:    fpop = Pavfp_RCPF;    goto do_32Fx4_unary;
4329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RSqrt32Fx4:    fpop = Pavfp_RSQRTF;  goto do_32Fx4_unary;
4330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I32UtoFx4:     fpop = Pavfp_CVTU2F;  goto do_32Fx4_unary;
4331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_I32StoFx4:     fpop = Pavfp_CVTS2F;  goto do_32Fx4_unary;
4332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QFtoI32Ux4_RZ: fpop = Pavfp_QCVTF2U; goto do_32Fx4_unary;
4333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QFtoI32Sx4_RZ: fpop = Pavfp_QCVTF2S; goto do_32Fx4_unary;
4334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RoundF32x4_RM: fpop = Pavfp_ROUNDM;  goto do_32Fx4_unary;
4335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RoundF32x4_RP: fpop = Pavfp_ROUNDP;  goto do_32Fx4_unary;
4336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RoundF32x4_RN: fpop = Pavfp_ROUNDN;  goto do_32Fx4_unary;
4337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_RoundF32x4_RZ: fpop = Pavfp_ROUNDZ;  goto do_32Fx4_unary;
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32Fx4_unary:
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
4342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_AvUn32Fx4(fpop, dst, arg));
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32UtoV128: {
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_aligned16, r_zeros;
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   dst = newVRegV(env);
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_sp( env, 32 );     // Move SP down
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Get a quadword aligned address within our stack space */
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_aligned16 = get_sp_aligned16( env );
4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off0  = PPCAMode_IR( 0,  r_aligned16 );
4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off4  = PPCAMode_IR( 4,  r_aligned16 );
4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off8  = PPCAMode_IR( 8,  r_aligned16 );
4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am_off12 = PPCAMode_IR( 12, r_aligned16 );
4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Store zeros */
4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r_zeros = newVRegI(env);
4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_LI(r_zeros, 0x0, mode64));
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_off0, r_zeros, mode64 ));
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_off4, r_zeros, mode64 ));
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_off8, r_zeros, mode64 ));
4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Store r_src in low word of quadword-aligned mem */
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_off12, r_src, mode64 ));
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Load word into low word of quadword vector reg */
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off12 ));
4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_sp( env, 32 );       // Reset SP
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup8x16:
4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup16x8:
4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Dup32x4:
4380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return mk_AvDuplicateRI(env, e->Iex.Unop.arg);
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* switch (e->Iex.Unop.op) */
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Unop) */
4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLtoV128: {
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) {
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r3, r2, r1, r0, r_aligned16;
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     dst = newVRegV(env);
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* do this via the stack (easy, convenient, etc) */
4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 32 );        // Move SP down
4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // get a quadword aligned address within our stack space
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r_aligned16 = get_sp_aligned16( env );
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off0  = PPCAMode_IR( 0,  r_aligned16 );
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off4  = PPCAMode_IR( 4,  r_aligned16 );
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off8  = PPCAMode_IR( 8,  r_aligned16 );
4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off12 = PPCAMode_IR( 12, r_aligned16 );
4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Do the less significant 64 bits */
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2);
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 4, am_off12, r0, mode64 ));
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 4, am_off8,  r1, mode64 ));
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Do the more significant 64 bits */
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1);
4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 4, am_off4, r2, mode64 ));
4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 4, am_off0, r3, mode64 ));
4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Fetch result back from stack. */
4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 32 );          // Reset SP
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     dst = newVRegV(env);
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     r_aligned16;
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PPCAMode *am_off0, *am_off8;
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* do this via the stack (easy, convenient, etc) */
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_sp( env, 32 );        // Move SP down
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // get a quadword aligned address within our stack space
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r_aligned16 = get_sp_aligned16( env );
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off0  = PPCAMode_IR( 0,  r_aligned16 );
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am_off8  = PPCAMode_IR( 8,  r_aligned16 );
4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Store 2*I64 to stack */
4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 8, am_off0, rHi, mode64 ));
4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Store( 8, am_off8, rLo, mode64 ));
4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Fetch result back from stack. */
4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_sp( env, 32 );          // Reset SP
4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Add32Fx4:   fpop = Pavfp_ADDF;   goto do_32Fx4;
4446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Sub32Fx4:   fpop = Pavfp_SUBF;   goto do_32Fx4;
4447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Max32Fx4:   fpop = Pavfp_MAXF;   goto do_32Fx4;
4448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Min32Fx4:   fpop = Pavfp_MINF;   goto do_32Fx4;
4449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_Mul32Fx4:   fpop = Pavfp_MULF;   goto do_32Fx4;
4450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpEQ32Fx4: fpop = Pavfp_CMPEQF; goto do_32Fx4;
4451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpGT32Fx4: fpop = Pavfp_CMPGTF; goto do_32Fx4;
4452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpGE32Fx4: fpop = Pavfp_CMPGEF; goto do_32Fx4;
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32Fx4:
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
4458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32Fx4: {
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* stay consistent with native ppc compares:
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if a left/right lane holds a nan, return zeros for that lane
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            so: le == NOT(gt OR isNan)
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          */
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg isNanLR = newVRegV(env);
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg isNanL = isNan(env, argL);
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg isNanR = isNan(env, argR);
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_OR, isNanLR,
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         isNanL, isNanR));
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin32Fx4(Pavfp_CMPGTF, dst,
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           argL, argR));
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(Pav_OR, dst, dst, isNanLR));
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AndV128:    op = Pav_AND;      goto do_AvBin;
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_OrV128:     op = Pav_OR;       goto do_AvBin;
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_XorV128:    op = Pav_XOR;      goto do_AvBin;
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvBin: {
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(op, dst, arg1, arg2));
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl8x16:    op = Pav_SHL;    goto do_AvBin8x16;
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr8x16:    op = Pav_SHR;    goto do_AvBin8x16;
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar8x16:    op = Pav_SAR;    goto do_AvBin8x16;
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol8x16:    op = Pav_ROTL;   goto do_AvBin8x16;
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI8x16: op = Pav_MRGHI;  goto do_AvBin8x16;
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO8x16: op = Pav_MRGLO;  goto do_AvBin8x16;
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x16:    op = Pav_ADDU;   goto do_AvBin8x16;
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux16:  op = Pav_QADDU;  goto do_AvBin8x16;
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx16:  op = Pav_QADDS;  goto do_AvBin8x16;
4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x16:    op = Pav_SUBU;   goto do_AvBin8x16;
4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux16:  op = Pav_QSUBU;  goto do_AvBin8x16;
4506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx16:  op = Pav_QSUBS;  goto do_AvBin8x16;
4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Ux16:   op = Pav_AVGU;   goto do_AvBin8x16;
4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Sx16:   op = Pav_AVGS;   goto do_AvBin8x16;
4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Ux16:   op = Pav_MAXU;   goto do_AvBin8x16;
4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Sx16:   op = Pav_MAXS;   goto do_AvBin8x16;
4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Ux16:   op = Pav_MINU;   goto do_AvBin8x16;
4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Sx16:   op = Pav_MINS;   goto do_AvBin8x16;
4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven8Ux16: op = Pav_OMULU;  goto do_AvBin8x16;
4514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven8Sx16: op = Pav_OMULS;  goto do_AvBin8x16;
4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x16:  op = Pav_CMPEQU; goto do_AvBin8x16;
4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Ux16: op = Pav_CMPGTU; goto do_AvBin8x16;
4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Sx16: op = Pav_CMPGTS; goto do_AvBin8x16;
4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvBin8x16: {
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin8x16(op, dst, arg1, arg2));
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl16x8:    op = Pav_SHL;    goto do_AvBin16x8;
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr16x8:    op = Pav_SHR;    goto do_AvBin16x8;
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar16x8:    op = Pav_SAR;    goto do_AvBin16x8;
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol16x8:    op = Pav_ROTL;   goto do_AvBin16x8;
4530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin16to8x16:    op = Pav_PACKUU;  goto do_AvBin16x8;
4531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Uto8Ux16: op = Pav_QPACKUU; goto do_AvBin16x8;
4532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16: op = Pav_QPACKSS; goto do_AvBin16x8;
4533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_InterleaveHI16x8:  op = Pav_MRGHI;  goto do_AvBin16x8;
4534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_InterleaveLO16x8:  op = Pav_MRGLO;  goto do_AvBin16x8;
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x8:    op = Pav_ADDU;   goto do_AvBin16x8;
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Ux8:  op = Pav_QADDU;  goto do_AvBin16x8;
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx8:  op = Pav_QADDS;  goto do_AvBin16x8;
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x8:    op = Pav_SUBU;   goto do_AvBin16x8;
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Ux8:  op = Pav_QSUBU;  goto do_AvBin16x8;
4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx8:  op = Pav_QSUBS;  goto do_AvBin16x8;
4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Ux8:   op = Pav_AVGU;   goto do_AvBin16x8;
4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Sx8:   op = Pav_AVGS;   goto do_AvBin16x8;
4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Ux8:   op = Pav_MAXU;   goto do_AvBin16x8;
4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Sx8:   op = Pav_MAXS;   goto do_AvBin16x8;
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Ux8:   op = Pav_MINU;   goto do_AvBin16x8;
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Sx8:   op = Pav_MINS;   goto do_AvBin16x8;
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven16Ux8: op = Pav_OMULU;  goto do_AvBin16x8;
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MullEven16Sx8: op = Pav_OMULS;  goto do_AvBin16x8;
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16x8:  op = Pav_CMPEQU; goto do_AvBin16x8;
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Ux8: op = Pav_CMPGTU; goto do_AvBin16x8;
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Sx8: op = Pav_CMPGTS; goto do_AvBin16x8;
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvBin16x8: {
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin16x8(op, dst, arg1, arg2));
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shl32x4:    op = Pav_SHL;    goto do_AvBin32x4;
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Shr32x4:    op = Pav_SHR;    goto do_AvBin32x4;
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sar32x4:    op = Pav_SAR;    goto do_AvBin32x4;
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Rol32x4:    op = Pav_ROTL;   goto do_AvBin32x4;
4564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin32to16x8:    op = Pav_PACKUU;  goto do_AvBin32x4;
4565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Uto16Ux8: op = Pav_QPACKUU; goto do_AvBin32x4;
4566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8: op = Pav_QPACKSS; goto do_AvBin32x4;
4567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_InterleaveHI32x4:  op = Pav_MRGHI;  goto do_AvBin32x4;
4568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_InterleaveLO32x4:  op = Pav_MRGLO;  goto do_AvBin32x4;
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32x4:    op = Pav_ADDU;   goto do_AvBin32x4;
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Ux4:  op = Pav_QADDU;  goto do_AvBin32x4;
4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd32Sx4:  op = Pav_QADDS;  goto do_AvBin32x4;
4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32x4:    op = Pav_SUBU;   goto do_AvBin32x4;
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Ux4:  op = Pav_QSUBU;  goto do_AvBin32x4;
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub32Sx4:  op = Pav_QSUBS;  goto do_AvBin32x4;
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg32Ux4:   op = Pav_AVGU;   goto do_AvBin32x4;
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg32Sx4:   op = Pav_AVGS;   goto do_AvBin32x4;
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Ux4:   op = Pav_MAXU;   goto do_AvBin32x4;
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Sx4:   op = Pav_MAXS;   goto do_AvBin32x4;
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Ux4:   op = Pav_MINU;   goto do_AvBin32x4;
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Sx4:   op = Pav_MINS;   goto do_AvBin32x4;
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32x4:  op = Pav_CMPEQU; goto do_AvBin32x4;
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Ux4: op = Pav_CMPGTU; goto do_AvBin32x4;
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Sx4: op = Pav_CMPGTS; goto do_AvBin32x4;
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvBin32x4: {
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin32x4(op, dst, arg1, arg2));
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN8x16: op = Pav_SHL; goto do_AvShift8x16;
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN8x16: op = Pav_SAR; goto do_AvShift8x16;
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvShift8x16: {
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst    = newVRegV(env);
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin8x16(op, dst, r_src, v_shft));
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x8: op = Pav_SHL; goto do_AvShift16x8;
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x8: op = Pav_SHR; goto do_AvShift16x8;
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x8: op = Pav_SAR; goto do_AvShift16x8;
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvShift16x8: {
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst    = newVRegV(env);
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin16x8(op, dst, r_src, v_shft));
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x4: op = Pav_SHL; goto do_AvShift32x4;
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x4: op = Pav_SHR; goto do_AvShift32x4;
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x4: op = Pav_SAR; goto do_AvShift32x4;
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvShift32x4: {
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst    = newVRegV(env);
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBin32x4(op, dst, r_src, v_shft));
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrV128: op = Pav_SHR; goto do_AvShiftV128;
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlV128: op = Pav_SHL; goto do_AvShiftV128;
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_AvShiftV128: {
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst    = newVRegV(env);
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: shift value gets masked by 127 */
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvBinary(op, dst, r_src, v_shft));
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Perm8x16: {
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst   = newVRegV(env);
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_src = iselVecExpr(env, e->Iex.Binop.arg1);
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_ctl = iselVecExpr(env, e->Iex.Binop.arg2);
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvPerm(dst, v_src, v_src, v_ctl));
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } /* switch (e->Iex.Binop.op) */
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const ) {
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_V128);
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Const.con->Ico.V128 == 0x0000) {
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return generate_zeroes_V128(env);
4652f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
4653f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      else if (e->Iex.Const.con->Ico.V128 == 0xffff) {
4654f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         return generate_ones_V128(env);
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselVecExpr(ppc) (subarch = %s): can't reduce\n",
4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              LibVEX_ppVexHwCaps(mode64 ? VexArchPPC64 : VexArchPPC32,
4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 env->hwcaps));
4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselVecExpr_wrk(ppc)");
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Statements                                  ---*/
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselStmt ( ISelEnv* env, IRStmt* stmt )
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool mode64 = env->mode64;
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n -- ");
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRStmt(stmt);
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (stmt->tag) {
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- STORE --------- */
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Store: {
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IREndness end   = stmt->Ist.Store.end;
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (end != Iend_BE)
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && (tya != Ity_I32))
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && (tya != Ity_I64))
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          (mode64 && (tyd == Ity_I64))) {
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(tyd)),
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       am_addr, r_src, mode64 ));
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_F64) {
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data);
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_F32) {
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_V128) {
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_src = iselVecExpr(env, stmt->Ist.Store.data);
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_I64 && !mode64) {
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Just calculate the address in the register.  Life is too
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            short to arse around trying and possibly failing to adjust
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the offset in a 'reg+offset' style amode. */
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rHi32, rLo32;
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr( &rHi32, &rLo32, env, stmt->Ist.Store.data );
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4/*byte-store*/,
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       PPCAMode_IR( 0, r_addr ),
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       rHi32,
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       False/*32-bit insn please*/) );
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4/*byte-store*/,
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       PPCAMode_IR( 4, r_addr ),
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       rLo32,
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       False/*32-bit insn please*/) );
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- PUT --------- */
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Put: {
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8  || ty == Ity_I16 ||
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          GuestStatePtr(mode64) );
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(ty)),
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       am_addr, r_src, mode64 ));
4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && ty == Ity_I64) {
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rHi, rLo;
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           GuestStatePtr(mode64) );
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr4 = advance4(env, am_addr);
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Put.data);
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_addr,  rHi, mode64 ));
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( 4, am_addr4, rLo, mode64 ));
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (ty == Ity_V128) {
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Guest state vectors are 16byte aligned,
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            so don't need to worry here */
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_src = iselVecExpr(env, stmt->Ist.Put.data);
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           GuestStatePtr(mode64) );
4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, stmt->Ist.Put.data);
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          GuestStatePtr(mode64) );
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        fr_src, am_addr ));
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (ty == Ity_D64) {
4788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_src = iselDfp64Expr( env, stmt->Ist.Put.data );
4789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
4790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          GuestStatePtr(mode64) );
4791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8, fr_src, am_addr ) );
4792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Indexed PUT --------- */
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_PutI: {
4799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRPutI *puti = stmt->Ist.PutI.details;
4800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PPCAMode* dst_am
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset(
4803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              env, puti->descr,
4804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   puti->ix, puti->bias );
4805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRType ty = typeOfIRExpr(env->type_env, puti->data);
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && ty == Ity_I64) {
4807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_src = iselWordExpr_R(env, puti->data);
4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( toUChar(8),
4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       dst_am, r_src, mode64 ));
4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((!mode64) && ty == Ity_I32) {
4813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_src = iselWordExpr_R(env, puti->data);
4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Store( toUChar(4),
4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       dst_am, r_src, mode64 ));
4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TMP --------- */
4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_WrTmp: {
4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmp = stmt->Ist.WrTmp.tmp;
4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRTemp(env->type_env, tmp);
4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8  || ty == Ity_I16 ||
4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = lookupIRTemp(env, tmp);
4828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
4829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR( r_dst, r_src ));
4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && ty == Ity_I64) {
4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
4834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data);
4836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
4837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
4838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && ty == Ity_I128) {
4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt128Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data);
4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!mode64 && ty == Ity_I128) {
4850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_srcHi, r_srcMedHi, r_srcMedLo, r_srcLo;
4851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dstHi, r_dstMedHi, r_dstMedLo, r_dstLo;
4852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselInt128Expr_to_32x4(&r_srcHi, &r_srcMedHi,
4854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                &r_srcMedLo, &r_srcLo,
4855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                env, stmt->Ist.WrTmp.data);
4856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         lookupIRTempQuad( &r_dstHi, &r_dstMedHi, &r_dstMedLo,
4858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           &r_dstLo, env, tmp);
4859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR(r_dstHi,    r_srcHi) );
4861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR(r_dstMedHi, r_srcMedHi) );
4862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR(r_dstMedLo, r_srcMedLo) );
4863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR(r_dstLo,    r_srcLo) );
4864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I1) {
4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PPCCondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data);
4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = lookupIRTemp(env, tmp);
4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_Set(cond, r_dst));
4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = lookupIRTemp(env, tmp);
4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselDblExpr(env, stmt->Ist.WrTmp.data);
4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F32) {
4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_dst = lookupIRTemp(env, tmp);
4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data);
4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_V128) {
4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_dst = lookupIRTemp(env, tmp);
4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg v_src = iselVecExpr(env, stmt->Ist.WrTmp.data);
4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, PPCInstr_AvUnary(Pav_MOV, v_dst, v_src));
4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (ty == Ity_D64) {
4891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_dst = lookupIRTemp( env, tmp );
4892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_src = iselDfp64Expr( env, stmt->Ist.WrTmp.data );
4893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dst, fr_src ) );
4894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (ty == Ity_D128) {
4897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_srcHi, fr_srcLo, fr_dstHi, fr_dstLo;
4898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	 //         lookupDfp128IRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
4899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         lookupIRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
4900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDfp128Expr( &fr_srcHi, &fr_srcLo, env, stmt->Ist.WrTmp.data );
4901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstHi, fr_srcHi ) );
4902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstLo, fr_srcLo ) );
4903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Load Linked or Store Conditional --------- */
4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_LLSC: {
4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res    = stmt->Ist.LLSC.result;
4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType tyRes  = typeOfIRTemp(env->type_env, res);
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt->Ist.LLSC.end != Iend_BE)
4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && (tyAddr != Ity_I32))
4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64 && (tyAddr != Ity_I64))
4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt->Ist.LLSC.storedata == NULL) {
4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* LL */
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_addr = iselWordExpr_R( env, stmt->Ist.LLSC.addr );
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst  = lookupIRTemp(env, res);
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tyRes == Ity_I32) {
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_LoadL( 4, r_dst, r_addr, mode64 ));
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tyRes == Ity_I64 && mode64) {
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_LoadL( 8, r_dst, r_addr, mode64 ));
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthru */;
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* SC */
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_res  = lookupIRTemp(env, res); /* :: Ity_I1 */
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_a    = iselWordExpr_R(env, stmt->Ist.LLSC.addr);
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_src  = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg   r_tmp  = newVRegI(env);
4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType tyData = typeOfIRExpr(env->type_env,
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      stmt->Ist.LLSC.storedata);
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(tyRes == Ity_I1);
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tyData == Ity_I32 || (tyData == Ity_I64 && mode64)) {
4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_StoreC( tyData==Ity_I32 ? 4 : 8,
4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           r_a, r_src, mode64 ));
4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_MfCR( r_tmp ));
4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Shft(
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Pshft_SHR,
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             env->mode64 ? False : True
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                /*F:64-bit, T:32-bit shift*/,
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             r_tmp, r_tmp,
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             PPCRH_Imm(False/*unsigned*/, 29)));
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Probably unnecessary, since the IR dest type is Ity_I1,
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               and so we are entitled to leave whatever junk we like
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               drifting round in the upper 31 or 63 bits of r_res.
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               However, for the sake of conservativeness .. */
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_Alu(
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Palu_AND,
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             r_res, r_tmp,
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             PPCRH_Imm(False/*signed*/, 1)));
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthru */
4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto stmt_fail;
4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Call to DIRTY helper --------- */
4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Dirty: {
4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType   retty;
4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty* d = stmt->Ist.Dirty.details;
4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool     passBBP = False;
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->nFxState == 0)
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(!d->needsBBP);
4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      passBBP = toBool(d->nFxState > 0 && d->needsBBP);
4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Marshal args, do the call, clear stack. */
4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall( env, passBBP, d->guard, d->cee, d->args );
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now figure out what to do with the returned value, if any. */
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->tmp == IRTemp_INVALID)
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No return value.  Nothing to do. */
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      retty = typeOfIRTemp(env->type_env, d->tmp);
4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64 && retty == Ity_I64) {
4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dstHi, r_dstLo;
4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The returned value is in %r3:%r4.  Park it in the
4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register-pair associated with tmp. */
4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         lookupIRTempPair( &r_dstHi, &r_dstLo, env, d->tmp);
4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstHi, hregPPC_GPR3(mode64)));
4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dstLo, hregPPC_GPR4(mode64)));
4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (retty == Ity_I8  || retty == Ity_I16 ||
4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          retty == Ity_I32 || ((retty == Ity_I64) && mode64)) {
4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The returned value is in %r3.  Park it in the register
5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            associated with tmp. */
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r_dst = lookupIRTemp(env, d->tmp);
5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MEM FENCE --------- */
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_MBE:
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (stmt->Ist.MBE.event) {
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Imbe_Fence:
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, PPCInstr_MFence());
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- INSTR MARK --------- */
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't generate any executable code ... */
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_IMark:
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- ABI HINT --------- */
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These have no meaning (denotation in the IR) and so we ignore
5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      them ... if any actually made it this far. */
5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_AbiHint:
5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- NO-OP --------- */
5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fairly self-explanatory, wouldn't you say? */
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_NoOp:
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- EXIT --------- */
5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Exit: {
5037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRConst* dst = stmt->Ist.Exit.dst;
5038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!mode64 && dst->tag != Ico_U32)
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselStmt(ppc): Ist_Exit: dst is not a 32-bit value");
5040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (mode64 && dst->tag != Ico_U64)
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselStmt(ppc64): Ist_Exit: dst is not a 64-bit value");
5042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      PPCCondCode cc    = iselCondCode(env, stmt->Ist.Exit.guard);
5044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      PPCAMode*   amCIA = PPCAMode_IR(stmt->Ist.Exit.offsIP,
5045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      hregPPC_GPR31(mode64));
5046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Case: boring transfer to known address */
5048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (stmt->Ist.Exit.jk == Ijk_Boring
5049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          || stmt->Ist.Exit.jk == Ijk_Call
5050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
5051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env->chainingAllowed) {
5052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. almost always true .. */
5053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Skip the event check at the dst if this is a forwards
5054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               edge. */
5055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool toFastEP
5056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               = mode64
5057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
5058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
5059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0) vex_printf("%s", toFastEP ? "Y" : ",");
5060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_XDirect(
5061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
5062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
5063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             amCIA, cc, toFastEP));
5064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
5065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. very occasionally .. */
5066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* We can't use chaining, so ask for an assisted transfer,
5067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               as that's the only alternative that is allowable. */
5068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
5069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_XAssisted(r, amCIA, cc, Ijk_Boring));
5070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
5071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
5072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Case: assisted transfer to arbitrary address */
5075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (stmt->Ist.Exit.jk) {
5076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Keep this list in sync with that in iselNext below */
5077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_ClientReq:
5078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_EmFail:
5079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_EmWarn:
5080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_NoDecode:
5081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_NoRedir:
5082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_SigBUS:
5083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_SigTRAP:
5084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Sys_syscall:
5085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_TInval:
5086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         {
5087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
5088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_XAssisted(r, amCIA, cc,
5089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             stmt->Ist.Exit.jk));
5090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
5091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
5092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
5093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
5094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Do we ever expect to see any other kind? */
5097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto stmt_fail;
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default: break;
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  stmt_fail:
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRStmt(stmt);
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselStmt(ppc)");
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Basic block terminators (Nexts)             ---*/
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselNext ( ISelEnv* env,
5113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       IRExpr* next, IRJumpKind jk, Int offsIP )
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
5116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf( "\n-- PUT(%d) = ", offsIP);
5117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppIRExpr( next );
5118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf( "; exit-");
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRJumpKind(jk);
5120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf( "\n");
5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   PPCCondCode always = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
5124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Case: boring transfer to known address */
5126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (next->tag == Iex_Const) {
5127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRConst* cdst = next->Iex.Const.con;
5128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
5129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (jk == Ijk_Boring || jk == Ijk_Call) {
5130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Boring transfer to known address */
5131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
5132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env->chainingAllowed) {
5133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. almost always true .. */
5134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Skip the event check at the dst if this is a forwards
5135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               edge. */
5136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool toFastEP
5137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               = env->mode64
5138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
5139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
5140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0) vex_printf("%s", toFastEP ? "X" : ".");
5141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_XDirect(
5142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             env->mode64 ? (Addr64)cdst->Ico.U64
5143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         : (Addr64)cdst->Ico.U32,
5144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             amCIA, always, toFastEP));
5145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
5146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. very occasionally .. */
5147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* We can't use chaining, so ask for an assisted transfer,
5148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               as that's the only alternative that is allowable. */
5149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r = iselWordExpr_R(env, next);
5150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
5151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             Ijk_Boring));
5152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
5153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
5154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
5156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Case: call/return (==boring) transfer to any address */
5158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (jk) {
5159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
5160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg       r     = iselWordExpr_R(env, next);
5161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCAMode*  amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
5162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env->chainingAllowed) {
5163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_XIndir(r, amCIA, always));
5164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
5165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
5166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             Ijk_Boring));
5167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
5168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
5169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
5171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
5172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
5173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Case: assisted transfer to arbitrary address */
5175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (jk) {
5176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Keep this list in sync with that for Ist_Exit above */
5177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_ClientReq:
5178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_EmFail:
5179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_EmWarn:
5180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_NoDecode:
5181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_NoRedir:
5182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_SigBUS:
5183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_SigTRAP:
5184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_Sys_syscall:
5185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_TInval:
5186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      {
5187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg      r     = iselWordExpr_R(env, next);
5188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
5189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, PPCInstr_XAssisted(r, amCIA, always, jk));
5190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
5191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
5193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
5194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
5195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf( "\n-- PUT(%d) = ", offsIP);
5197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr( next );
5198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf( "; exit-");
5199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRJumpKind(jk);
5200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf( "\n");
5201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(0); // are we expecting any other kind?
5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Insn selector top-level                           ---*/
5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Translate an entire SB to ppc code. */
5210663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengHInstrArray* iselSB_PPC ( IRSB* bb,
5211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          VexArch      arch_host,
5212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          VexArchInfo* archinfo_host,
5213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          VexAbiInfo*  vbi,
5214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Int offs_Host_EvC_Counter,
5215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Int offs_Host_EvC_FailAddr,
5216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Bool chainingAllowed,
5217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Bool addProfInc,
5218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          Addr64 max_ga )
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int       i, j;
5221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg      hregLo, hregMedLo, hregMedHi, hregHi;
5222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ISelEnv*  env;
5223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt      hwcaps_host = archinfo_host->hwcaps;
5224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool      mode64 = False;
5225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt      mask32, mask64;
5226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   PPCAMode *amCounter, *amFailAddr;
5227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(arch_host == VexArchPPC32 || arch_host == VexArchPPC64);
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mode64 = arch_host == VexArchPPC64;
5231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (!mode64) vassert(max_ga <= 0xFFFFFFFFULL);
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* do some sanity checks */
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
5235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
5236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            | VEX_HWCAPS_PPC32_DFP;
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
5239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	   | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP;
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode64) {
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert((hwcaps_host & mask32) == 0);
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert((hwcaps_host & mask64) == 0);
5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make up an initial environment to use. */
5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env = LibVEX_Alloc(sizeof(ISelEnv));
5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr = 0;
5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Are we being ppc32 or ppc64? */
5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->mode64 = mode64;
5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up output code array. */
5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->code = newHInstrArray();
5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy BB's type env. */
5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->type_env = bb->tyenv;
5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
5261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    * change as we go along.
5262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    *
5263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    * vregmap2 and vregmap3 are only used in 32 bit mode
5264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    * for supporting I128 in 32-bit mode
5265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    */
5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->n_vregmap = bb->tyenv->types_used;
5267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vregmapLo    = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
5268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vregmapMedLo = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
5269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (mode64) {
5270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      env->vregmapMedHi = NULL;
5271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      env->vregmapHi    = NULL;
5272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
5273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      env->vregmapMedHi = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
5274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      env->vregmapHi    = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
5275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* and finally ... */
5278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->chainingAllowed = chainingAllowed;
5279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->max_ga          = max_ga;
5280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->hwcaps          = hwcaps_host;
5281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->previous_rm     = NULL;
5282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vbi             = vbi;
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For each IR temporary, allocate a suitably-kinded virtual
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register. */
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   j = 0;
5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < env->n_vregmap; i++) {
5288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      hregLo = hregMedLo = hregMedHi = hregHi = INVALID_HREG;
5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (bb->tyenv->types[i]) {
5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I1:
5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I8:
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I16:
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I32:
5294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (mode64) { hregLo    = mkHReg(j++, HRcInt64,  True); break;
5295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {      hregLo    = mkHReg(j++, HRcInt32,  True); break;
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_I64:
5298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (mode64) { hregLo    = mkHReg(j++, HRcInt64,  True); break;
5299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {      hregLo    = mkHReg(j++, HRcInt32,  True);
5300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         hregMedLo = mkHReg(j++, HRcInt32,  True); break;
5301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
5302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ity_I128:
5303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (mode64) { hregLo    = mkHReg(j++, HRcInt64,  True);
5304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         hregMedLo = mkHReg(j++, HRcInt64,  True); break;
5305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {      hregLo    = mkHReg(j++, HRcInt32,  True);
5306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         hregMedLo = mkHReg(j++, HRcInt32,  True);
5307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         hregMedHi = mkHReg(j++, HRcInt32,  True);
5308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         hregHi    = mkHReg(j++, HRcInt32,  True); break;
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ity_F32:
5311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ity_F64:    hregLo    = mkHReg(j++, HRcFlt64,  True); break;
5312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ity_V128:   hregLo    = mkHReg(j++, HRcVec128, True); break;
5313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ity_D64:    hregLo    = mkHReg(j++, HRcFlt64,  True); break;
5314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ity_D128:   hregLo    = mkHReg(j++, HRcFlt64,  True);
5315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      hregMedLo = mkHReg(j++, HRcFlt64,  True); break;
5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRType(bb->tyenv->types[i]);
5318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselBB(ppc): IRTemp type");
5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      env->vregmapLo[i]    = hregLo;
5321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      env->vregmapMedLo[i] = hregMedLo;
5322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!mode64) {
5323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         env->vregmapMedHi[i] = hregMedHi;
5324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         env->vregmapHi[i]    = hregHi;
5325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr = j;
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The very first instruction must be an event check. */
5330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   amCounter  = PPCAMode_IR(offs_Host_EvC_Counter, hregPPC_GPR31(mode64));
5331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   amFailAddr = PPCAMode_IR(offs_Host_EvC_FailAddr, hregPPC_GPR31(mode64));
5332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, PPCInstr_EvCheck(amCounter, amFailAddr));
5333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
5334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Possibly a block counter increment (for profiling).  At this
5335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      point we don't know the address of the counter, so just pretend
5336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      it is zero.  It will have to be patched later, but before this
5337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      translation is used, by a call to LibVEX_patchProfCtr. */
5338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (addProfInc) {
5339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, PPCInstr_ProfInc());
5340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, finally we can iterate over the statements. */
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++)
5344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      iselStmt(env, bb->stmts[i]);
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* record the number of vregs we used. */
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->code->n_vregs = env->vreg_ctr;
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return env->code;
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                     host_ppc_isel.c ---*/
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5357