1 
2 /*---------------------------------------------------------------*/
3 /*--- begin                                   host_ppc_isel.c ---*/
4 /*---------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2004-2017 OpenWorks LLP
11       info@open-works.net
12 
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17 
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 
30    Neither the names of the U.S. Department of Energy nor the
31    University of California nor the names of its contributors may be
32    used to endorse or promote products derived from this software
33    without prior written permission.
34 */
35 
36 #include "libvex_basictypes.h"
37 #include "libvex_ir.h"
38 #include "libvex.h"
39 
40 #include "ir_match.h"
41 #include "main_util.h"
42 #include "main_globals.h"
43 #include "host_generic_regs.h"
44 #include "host_generic_simd64.h"
45 #include "host_ppc_defs.h"
46 
47 /* GPR register class for ppc32/64 */
48 #define HRcGPR(_mode64) ((_mode64) ? HRcInt64 : HRcInt32)
49 
50 
51 /*---------------------------------------------------------*/
52 /*--- Register Usage Conventions                        ---*/
53 /*---------------------------------------------------------*/
54 /*
55   Integer Regs
56   ------------
57   GPR0       Reserved
58   GPR1       Stack Pointer
59   GPR2       not used - TOC pointer
60   GPR3:10    Allocateable
61   GPR11      if mode64: not used - calls by ptr / env ptr for some langs
62   GPR12      if mode64: not used - exceptions / global linkage code
63   GPR13      not used - Thread-specific pointer
64   GPR14:28   Allocateable
65   GPR29      Unused by us (reserved for the dispatcher)
66   GPR30      AltiVec temp spill register
67   GPR31      GuestStatePointer
68 
69   Of Allocateable regs:
70   if (mode64)
71     GPR3:10  Caller-saved regs
72   else
73     GPR3:12  Caller-saved regs
74   GPR14:29   Callee-saved regs
75 
76   GPR3       [Return | Parameter] - carrying reg
77   GPR4:10    Parameter-carrying regs
78 
79 
80   Floating Point Regs
81   -------------------
82   FPR0:31    Allocateable
83 
84   FPR0       Caller-saved - scratch reg
85   if (mode64)
86     FPR1:13  Caller-saved - param & return regs
87   else
88     FPR1:8   Caller-saved - param & return regs
89     FPR9:13  Caller-saved regs
90   FPR14:31   Callee-saved regs
91 
92 
93   Vector Regs (on processors with the VMX feature)
94   -----------
95   VR0-VR1    Volatile scratch registers
96   VR2-VR13   Volatile vector parameters registers
97   VR14-VR19  Volatile scratch registers
98   VR20-VR31  Non-volatile registers
99   VRSAVE     Non-volatile 32-bit register
100 */
101 
102 
103 /*---------------------------------------------------------*/
104 /*--- PPC FP Status & Control Register Conventions      ---*/
105 /*---------------------------------------------------------*/
106 /*
107   Vex-generated code expects to run with the FPU set as follows: all
108   exceptions masked.  The rounding mode is set appropriately before
109   each floating point insn emitted (or left unchanged if known to be
110   correct already).  There are a few fp insns (fmr,fneg,fabs,fnabs),
111   which are unaffected by the rm and so the rounding mode is not set
112   prior to them.
113 
114   At least on MPC7447A (Mac Mini), frsqrte is also not affected by
115   rounding mode.  At some point the ppc docs get sufficiently vague
116   that the only way to find out is to write test programs.
117 */
118 /* Notes on the FP instruction set, 6 Feb 06.
119 
120 What                 exns -> CR1 ?   Sets FPRF ?   Observes RM ?
121 -------------------------------------------------------------
122 
123 fmr[.]                   if .             n             n
124 fneg[.]                  if .             n             n
125 fabs[.]                  if .             n             n
126 fnabs[.]                 if .             n             n
127 
128 fadd[.]                  if .             y             y
129 fadds[.]                 if .             y             y
130 fcfid[.] (Si64->dbl)     if .             y             y
131 fcfidU[.] (Ui64->dbl)    if .             y             y
132 fcfids[.] (Si64->sngl)   if .             Y             Y
133 fcfidus[.] (Ui64->sngl)  if .             Y             Y
134 fcmpo (cmp, result       n                n             n
135 fcmpu  to crfD)          n                n             n
136 fctid[.]  (dbl->i64)     if .       ->undef             y
137 fctidz[.] (dbl->i64)     if .       ->undef    rounds-to-zero
138 fctiw[.]  (dbl->i32)     if .       ->undef             y
139 fctiwz[.] (dbl->i32)     if .       ->undef    rounds-to-zero
140 fdiv[.]                  if .             y             y
141 fdivs[.]                 if .             y             y
142 fmadd[.]                 if .             y             y
143 fmadds[.]                if .             y             y
144 fmsub[.]                 if .             y             y
145 fmsubs[.]                if .             y             y
146 fmul[.]                  if .             y             y
147 fmuls[.]                 if .             y             y
148 
149 (note: for fnm*, rounding happens before final negation)
150 fnmadd[.]                if .             y             y
151 fnmadds[.]               if .             y             y
152 fnmsub[.]                if .             y             y
153 fnmsubs[.]               if .             y             y
154 
155 fre[.]                   if .             y             y
156 fres[.]                  if .             y             y
157 
158 frsqrte[.]               if .             y       apparently not
159 
160 fsqrt[.]                 if .             y             y
161 fsqrts[.]                if .             y             y
162 fsub[.]                  if .             y             y
163 fsubs[.]                 if .             y             y
164 
165 
166 fpscr: bits 30-31 (ibm) is RM
167             24-29 (ibm) are exnmasks/non-IEEE bit, all zero
168 	    15-19 (ibm) is FPRF: class, <, =, >, UNord
169 
170 ppc fe(guest) makes fpscr read as all zeros except RM (and maybe FPRF
171 in future)
172 
173 mcrfs     - move fpscr field to CR field
174 mtfsfi[.] - 4 bit imm moved to fpscr field
175 mtfsf[.]  - move frS[low 1/2] to fpscr but using 8-bit field mask
176 mtfsb1[.] - set given fpscr bit
177 mtfsb0[.] - clear given fpscr bit
178 mffs[.]   - move all fpscr to frD[low 1/2]
179 
180 For [.] presumably cr1 is set with exn summary bits, as per
181 main FP insns
182 
183 A single precision store truncates/denormalises the in-register value,
184 but does not round it.  This is so that flds followed by fsts is
185 always the identity.
186 */
187 
188 
189 /*---------------------------------------------------------*/
190 /*--- misc helpers                                      ---*/
191 /*---------------------------------------------------------*/
192 
193 /* These are duplicated in guest-ppc/toIR.c */
unop(IROp op,IRExpr * a)194 static IRExpr* unop ( IROp op, IRExpr* a )
195 {
196    return IRExpr_Unop(op, a);
197 }
198 
mkU32(UInt i)199 static IRExpr* mkU32 ( UInt i )
200 {
201    return IRExpr_Const(IRConst_U32(i));
202 }
203 
bind(Int binder)204 static IRExpr* bind ( Int binder )
205 {
206    return IRExpr_Binder(binder);
207 }
208 
isZeroU8(IRExpr * e)209 static Bool isZeroU8 ( IRExpr* e )
210 {
211    return e->tag == Iex_Const
212           && e->Iex.Const.con->tag == Ico_U8
213           && e->Iex.Const.con->Ico.U8 == 0;
214 }
215 
216 
217 /*---------------------------------------------------------*/
218 /*--- ISelEnv                                           ---*/
219 /*---------------------------------------------------------*/
220 
221 /* This carries around:
222 
223    - A mapping from IRTemp to IRType, giving the type of any IRTemp we
224      might encounter.  This is computed before insn selection starts,
225      and does not change.
226 
227    - A mapping from IRTemp to HReg.  This tells the insn selector
228      which virtual register(s) are associated with each IRTemp
229      temporary.  This is computed before insn selection starts, and
230      does not change.  We expect this mapping to map precisely the
231      same set of IRTemps as the type mapping does.
232 
233          - vregmapLo    holds the primary register for the IRTemp.
234          - vregmapMedLo holds the secondary register for the IRTemp,
235               if any is needed.  That's only for Ity_I64 temps
236               in 32 bit mode or Ity_I128 temps in 64-bit mode.
237          - vregmapMedHi is only for dealing with Ity_I128 temps in
238               32 bit mode.  It holds bits 95:64 (Intel numbering)
239               of the IRTemp.
240          - vregmapHi is also only for dealing with Ity_I128 temps
241               in 32 bit mode.  It holds the most significant bits
242               (127:96 in Intel numbering) of the IRTemp.
243 
244     - The code array, that is, the insns selected so far.
245 
246     - A counter, for generating new virtual registers.
247 
248     - The host subarchitecture we are selecting insns for.
249       This is set at the start and does not change.
250 
251     - A Bool to tell us if the host is 32 or 64bit.
252       This is set at the start and does not change.
253 
254     - An IRExpr*, which may be NULL, holding the IR expression (an
255       IRRoundingMode-encoded value) to which the FPU's rounding mode
256       was most recently set.  Setting to NULL is always safe.  Used to
257       avoid redundant settings of the FPU's rounding mode, as
258       described in set_FPU_rounding_mode below.
259 
260     - A VexMiscInfo*, needed for knowing how to generate
261       function calls for this target.
262 
263     - The maximum guest address of any guest insn in this block.
264       Actually, the address of the highest-addressed byte from any
265       insn in this block.  Is set at the start and does not change.
266       This is used for detecting jumps which are definitely
267       forward-edges from this block, and therefore can be made
268       (chained) to the fast entry point of the destination, thereby
269       avoiding the destination's event check.
270 */
271 
272 typedef
273    struct {
274       /* Constant -- are set at the start and do not change. */
275       IRTypeEnv* type_env;
276                               //    64-bit mode              32-bit mode
277       HReg*    vregmapLo;     // Low 64-bits [63:0]    Low 32-bits     [31:0]
278       HReg*    vregmapMedLo;  // high 64-bits[127:64]  Next 32-bits    [63:32]
279       HReg*    vregmapMedHi;  // unused                Next 32-bits    [95:64]
280       HReg*    vregmapHi;     // unused                highest 32-bits [127:96]
281       Int      n_vregmap;
282 
283       /* 27 Jan 06: Not currently used, but should be */
284       UInt         hwcaps;
285 
286       Bool         mode64;
287 
288       const VexAbiInfo*  vbi;   // unused
289 
290       Bool         chainingAllowed;
291       Addr64       max_ga;
292 
293       /* These are modified as we go along. */
294       HInstrArray* code;
295       Int          vreg_ctr;
296 
297       IRExpr*      previous_rm;
298    }
299    ISelEnv;
300 
301 
lookupIRTemp(ISelEnv * env,IRTemp tmp)302 static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
303 {
304    vassert(tmp >= 0);
305    vassert(tmp < env->n_vregmap);
306    return env->vregmapLo[tmp];
307 }
308 
lookupIRTempPair(HReg * vrHI,HReg * vrLO,ISelEnv * env,IRTemp tmp)309 static void lookupIRTempPair ( HReg* vrHI, HReg* vrLO,
310                                ISelEnv* env, IRTemp tmp )
311 {
312    vassert(tmp >= 0);
313    vassert(tmp < env->n_vregmap);
314    vassert(! hregIsInvalid(env->vregmapMedLo[tmp]));
315    *vrLO = env->vregmapLo[tmp];
316    *vrHI = env->vregmapMedLo[tmp];
317 }
318 
319 /* Only for used in 32-bit mode */
lookupIRTempQuad(HReg * vrHi,HReg * vrMedHi,HReg * vrMedLo,HReg * vrLo,ISelEnv * env,IRTemp tmp)320 static void lookupIRTempQuad ( HReg* vrHi, HReg* vrMedHi, HReg* vrMedLo,
321                                HReg* vrLo, ISelEnv* env, IRTemp tmp )
322 {
323    vassert(!env->mode64);
324    vassert(tmp >= 0);
325    vassert(tmp < env->n_vregmap);
326    vassert(! hregIsInvalid(env->vregmapMedLo[tmp]));
327    *vrHi    = env->vregmapHi[tmp];
328    *vrMedHi = env->vregmapMedHi[tmp];
329    *vrMedLo = env->vregmapMedLo[tmp];
330    *vrLo    = env->vregmapLo[tmp];
331 }
332 
addInstr(ISelEnv * env,PPCInstr * instr)333 static void addInstr ( ISelEnv* env, PPCInstr* instr )
334 {
335    addHInstr(env->code, instr);
336    if (vex_traceflags & VEX_TRACE_VCODE) {
337       ppPPCInstr(instr, env->mode64);
338       vex_printf("\n");
339    }
340 }
341 
newVRegI(ISelEnv * env)342 static HReg newVRegI ( ISelEnv* env )
343 {
344    HReg reg
345       = mkHReg(True/*vreg*/, HRcGPR(env->mode64), 0/*enc*/, env->vreg_ctr);
346    env->vreg_ctr++;
347    return reg;
348 }
349 
newVRegF(ISelEnv * env)350 static HReg newVRegF ( ISelEnv* env )
351 {
352    HReg reg = mkHReg(True/*vreg*/, HRcFlt64, 0/*enc*/, env->vreg_ctr);
353    env->vreg_ctr++;
354    return reg;
355 }
356 
newVRegV(ISelEnv * env)357 static HReg newVRegV ( ISelEnv* env )
358 {
359    HReg reg = mkHReg(True/*vreg*/, HRcVec128, 0/*enc*/, env->vreg_ctr);
360    env->vreg_ctr++;
361    return reg;
362 }
363 
364 
365 /*---------------------------------------------------------*/
366 /*--- ISEL: Forward declarations                        ---*/
367 /*---------------------------------------------------------*/
368 
369 /* These are organised as iselXXX and iselXXX_wrk pairs.  The
370    iselXXX_wrk do the real work, but are not to be called directly.
371    For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
372    checks that all returned registers are virtual.  You should not
373    call the _wrk version directly.
374 
375    'Word' refers to the size of the native machine word, that is,
376    32-bit int in 32-bit mode and 64-bit int in 64-bit mode.  '2Word'
377    therefore refers to a double-width (64/128-bit) quantity in two
378    integer registers.
379 */
380 /* 32-bit mode: compute an I8/I16/I32 into a GPR.
381    64-bit mode: compute an I8/I16/I32/I64 into a GPR. */
382 static HReg          iselWordExpr_R_wrk ( ISelEnv* env, const IRExpr* e,
383                                           IREndness IEndianess );
384 static HReg          iselWordExpr_R     ( ISelEnv* env, const IRExpr* e,
385                                           IREndness IEndianess );
386 
387 /* 32-bit mode: Compute an I8/I16/I32 into a RH
388                 (reg-or-halfword-immediate).
389    64-bit mode: Compute an I8/I16/I32/I64 into a RH
390                 (reg-or-halfword-immediate).
391    It's important to specify whether the immediate is to be regarded
392    as signed or not.  If yes, this will never return -32768 as an
393    immediate; this guaranteed that all signed immediates that are
394    return can have their sign inverted if need be.
395 */
396 static PPCRH*        iselWordExpr_RH_wrk ( ISelEnv* env,
397                                            Bool syned, const IRExpr* e,
398                                            IREndness IEndianess );
399 static PPCRH*        iselWordExpr_RH     ( ISelEnv* env,
400                                            Bool syned, const IRExpr* e,
401                                            IREndness IEndianess );
402 
403 /* 32-bit mode: compute an I32 into a RI (reg or 32-bit immediate).
404    64-bit mode: compute an I64 into a RI (reg or 64-bit immediate). */
405 static PPCRI*        iselWordExpr_RI_wrk ( ISelEnv* env, const IRExpr* e,
406                                            IREndness IEndianess );
407 static PPCRI*        iselWordExpr_RI     ( ISelEnv* env, const IRExpr* e,
408                                            IREndness IEndianess );
409 
410 /* In 32 bit mode ONLY, compute an I8 into a
411    reg-or-5-bit-unsigned-immediate, the latter being an immediate in
412    the range 1 .. 31 inclusive.  Used for doing shift amounts. */
413 static PPCRH*        iselWordExpr_RH5u_wrk ( ISelEnv* env, const IRExpr* e,
414                                              IREndness IEndianess );
415 static PPCRH*        iselWordExpr_RH5u     ( ISelEnv* env, const IRExpr* e,
416                                              IREndness IEndianess );
417 
418 /* In 64-bit mode ONLY, compute an I8 into a
419    reg-or-6-bit-unsigned-immediate, the latter being an immediate in
420    the range 1 .. 63 inclusive.  Used for doing shift amounts. */
421 static PPCRH*        iselWordExpr_RH6u_wrk ( ISelEnv* env, const IRExpr* e,
422                                              IREndness IEndianess );
423 static PPCRH*        iselWordExpr_RH6u     ( ISelEnv* env, const IRExpr* e,
424                                              IREndness IEndianess );
425 
426 /* 32-bit mode: compute an I32 into an AMode.
427    64-bit mode: compute an I64 into an AMode.
428 
429    Requires to know (xferTy) the type of data to be loaded/stored
430    using this amode.  That is so that, for 64-bit code generation, any
431    PPCAMode_IR returned will have an index (immediate offset) field
432    that is guaranteed to be 4-aligned, if there is any chance that the
433    amode is to be used in ld/ldu/lda/std/stdu.
434 
435    Since there are no such restrictions on 32-bit insns, xferTy is
436    ignored for 32-bit code generation. */
437 static PPCAMode*     iselWordExpr_AMode_wrk ( ISelEnv* env, const IRExpr* e,
438                                               IRType xferTy,
439                                               IREndness IEndianess );
440 static PPCAMode*     iselWordExpr_AMode     ( ISelEnv* env, const IRExpr* e,
441                                               IRType xferTy,
442                                               IREndness IEndianess );
443 
444 static void iselInt128Expr_to_32x4_wrk ( HReg* rHi, HReg* rMedHi,
445                                          HReg* rMedLo, HReg* rLo,
446                                          ISelEnv* env, const IRExpr* e,
447                                          IREndness IEndianess );
448 static void iselInt128Expr_to_32x4     ( HReg* rHi, HReg* rMedHi,
449                                          HReg* rMedLo, HReg* rLo,
450                                          ISelEnv* env, const IRExpr* e,
451                                          IREndness IEndianess );
452 
453 
454 /* 32-bit mode ONLY: compute an I64 into a GPR pair. */
455 static void          iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
456                                          ISelEnv* env, const IRExpr* e,
457                                          IREndness IEndianess );
458 static void          iselInt64Expr     ( HReg* rHi, HReg* rLo,
459                                          ISelEnv* env, const IRExpr* e,
460                                          IREndness IEndianess );
461 
462 /* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
463 static void          iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
464                                           ISelEnv* env, const IRExpr* e,
465                                           IREndness IEndianess );
466 
467 static void          iselInt128Expr     ( HReg* rHi, HReg* rLo,
468                                           ISelEnv* env, const IRExpr* e,
469                                           IREndness IEndianess );
470 
471 static PPCCondCode   iselCondCode_wrk ( ISelEnv* env, const IRExpr* e,
472                                         IREndness IEndianess );
473 static PPCCondCode   iselCondCode     ( ISelEnv* env, const IRExpr* e,
474                                         IREndness IEndianess );
475 
476 static HReg          iselDblExpr_wrk ( ISelEnv* env, const IRExpr* e,
477                                        IREndness IEndianess );
478 static HReg          iselDblExpr     ( ISelEnv* env, const IRExpr* e,
479                                        IREndness IEndianess );
480 
481 static HReg          iselFltExpr_wrk ( ISelEnv* env, const IRExpr* e,
482                                        IREndness IEndianess );
483 static HReg          iselFltExpr     ( ISelEnv* env, const IRExpr* e,
484                                        IREndness IEndianess );
485 
486 static HReg          iselVecExpr_wrk ( ISelEnv* env, const IRExpr* e,
487                                        IREndness IEndianess );
488 static HReg          iselVecExpr     ( ISelEnv* env, const IRExpr* e,
489                                        IREndness IEndianess );
490 
491 /* 64-bit mode ONLY. */
492 static HReg          iselDfp32Expr_wrk ( ISelEnv* env, const IRExpr* e,
493                                          IREndness IEndianess );
494 static HReg          iselDfp32Expr     ( ISelEnv* env, const IRExpr* e,
495                                          IREndness IEndianess );
496 static HReg          iselDfp64Expr_wrk ( ISelEnv* env, const IRExpr* e,
497                                          IREndness IEndianess );
498 static HReg          iselDfp64Expr     ( ISelEnv* env, const IRExpr* e,
499                                          IREndness IEndianess );
500 static HReg iselFp128Expr_wrk ( ISelEnv* env, const IRExpr* e,
501                                 IREndness IEndianess);
502 static HReg iselFp128Expr     ( ISelEnv* env, const IRExpr* e,
503                                 IREndness IEndianess);
504 
505 /* 64-bit mode ONLY: compute an D128 into a GPR64 pair. */
506 static void iselDfp128Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env,
507                                  const IRExpr* e, IREndness IEndianess );
508 static void iselDfp128Expr     ( HReg* rHi, HReg* rLo, ISelEnv* env,
509                                  const IRExpr* e, IREndness IEndianess );
510 
511 /*---------------------------------------------------------*/
512 /*--- ISEL: Misc helpers                                ---*/
513 /*---------------------------------------------------------*/
514 
515 /* Make an int reg-reg move. */
516 
mk_iMOVds_RR(HReg r_dst,HReg r_src)517 static PPCInstr* mk_iMOVds_RR ( HReg r_dst, HReg r_src )
518 {
519    vassert(hregClass(r_dst) == hregClass(r_src));
520    vassert(hregClass(r_src) ==  HRcInt32 ||
521            hregClass(r_src) ==  HRcInt64);
522    return PPCInstr_Alu(Palu_OR, r_dst, r_src, PPCRH_Reg(r_src));
523 }
524 
525 /* Advance/retreat %r1 by n. */
526 
add_to_sp(ISelEnv * env,UInt n)527 static void add_to_sp ( ISelEnv* env, UInt n )
528 {
529    HReg sp = StackFramePtr(env->mode64);
530    vassert(n <= 1024 && (n%16) == 0);
531    addInstr(env, PPCInstr_Alu( Palu_ADD, sp, sp,
532                                PPCRH_Imm(True,toUShort(n)) ));
533 }
534 
sub_from_sp(ISelEnv * env,UInt n)535 static void sub_from_sp ( ISelEnv* env, UInt n )
536 {
537    HReg sp = StackFramePtr(env->mode64);
538    vassert(n <= 1024 && (n%16) == 0);
539    addInstr(env, PPCInstr_Alu( Palu_SUB, sp, sp,
540                                PPCRH_Imm(True,toUShort(n)) ));
541 }
542 
543 /*
544   returns a quadword aligned address on the stack
545    - copies SP, adds 16bytes, aligns to quadword.
546   use sub_from_sp(32) before calling this,
547   as expects to have 32 bytes to play with.
548 */
get_sp_aligned16(ISelEnv * env)549 static HReg get_sp_aligned16 ( ISelEnv* env )
550 {
551    HReg       r = newVRegI(env);
552    HReg align16 = newVRegI(env);
553    addInstr(env, mk_iMOVds_RR(r, StackFramePtr(env->mode64)));
554    // add 16
555    addInstr(env, PPCInstr_Alu( Palu_ADD, r, r,
556                                PPCRH_Imm(True,toUShort(16)) ));
557    // mask to quadword
558    addInstr(env,
559             PPCInstr_LI(align16, 0xFFFFFFFFFFFFFFF0ULL, env->mode64));
560    addInstr(env, PPCInstr_Alu(Palu_AND, r,r, PPCRH_Reg(align16)));
561    return r;
562 }
563 
564 
565 
566 /* Load 2*I32 regs to fp reg */
mk_LoadRR32toFPR(ISelEnv * env,HReg r_srcHi,HReg r_srcLo)567 static HReg mk_LoadRR32toFPR ( ISelEnv* env,
568                                HReg r_srcHi, HReg r_srcLo )
569 {
570    HReg fr_dst = newVRegF(env);
571    PPCAMode *am_addr0, *am_addr1;
572 
573    vassert(!env->mode64);
574    vassert(hregClass(r_srcHi) == HRcInt32);
575    vassert(hregClass(r_srcLo) == HRcInt32);
576 
577    sub_from_sp( env, 16 );        // Move SP down 16 bytes
578    am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
579    am_addr1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
580 
581    // store hi,lo as Ity_I32's
582    addInstr(env, PPCInstr_Store( 4, am_addr0, r_srcHi, env->mode64 ));
583    addInstr(env, PPCInstr_Store( 4, am_addr1, r_srcLo, env->mode64 ));
584 
585    // load as float
586    addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));
587 
588    add_to_sp( env, 16 );          // Reset SP
589    return fr_dst;
590 }
591 
592 /* Load I64 reg to fp reg */
mk_LoadR64toFPR(ISelEnv * env,HReg r_src)593 static HReg mk_LoadR64toFPR ( ISelEnv* env, HReg r_src )
594 {
595    HReg fr_dst = newVRegF(env);
596    PPCAMode *am_addr0;
597 
598    vassert(env->mode64);
599    vassert(hregClass(r_src) == HRcInt64);
600 
601    sub_from_sp( env, 16 );        // Move SP down 16 bytes
602    am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
603 
604    // store as Ity_I64
605    addInstr(env, PPCInstr_Store( 8, am_addr0, r_src, env->mode64 ));
606 
607    // load as float
608    addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));
609 
610    add_to_sp( env, 16 );          // Reset SP
611    return fr_dst;
612 }
613 
614 
615 /* Given an amode, return one which references 4 bytes further
616    along. */
617 
advance4(ISelEnv * env,PPCAMode * am)618 static PPCAMode* advance4 ( ISelEnv* env, PPCAMode* am )
619 {
620    PPCAMode* am4 = dopyPPCAMode( am );
621    if (am4->tag == Pam_IR
622        && am4->Pam.IR.index + 4 <= 32767) {
623       am4->Pam.IR.index += 4;
624    } else {
625       vpanic("advance4(ppc,host)");
626    }
627    return am4;
628 }
629 
630 
631 /* Given a guest-state array descriptor, an index expression and a
632    bias, generate a PPCAMode pointing at the relevant piece of
633    guest state.  */
634 static
genGuestArrayOffset(ISelEnv * env,IRRegArray * descr,IRExpr * off,Int bias,IREndness IEndianess)635 PPCAMode* genGuestArrayOffset ( ISelEnv* env, IRRegArray* descr,
636                                 IRExpr* off, Int bias, IREndness IEndianess )
637 {
638    HReg rtmp, roff;
639    Int  elemSz = sizeofIRType(descr->elemTy);
640    Int  nElems = descr->nElems;
641    Int  shift  = 0;
642 
643    /* Throw out any cases we don't need.  In theory there might be a
644       day where we need to handle others, but not today. */
645 
646    if (nElems != 16 && nElems != 32)
647       vpanic("genGuestArrayOffset(ppc host)(1)");
648 
649    switch (elemSz) {
650       case 4:  shift = 2; break;
651       case 8:  shift = 3; break;
652       default: vpanic("genGuestArrayOffset(ppc host)(2)");
653    }
654 
655    if (bias < -100 || bias > 100) /* somewhat arbitrarily */
656       vpanic("genGuestArrayOffset(ppc host)(3)");
657    if (descr->base < 0 || descr->base > 5000) /* somewhat arbitrarily */
658       vpanic("genGuestArrayOffset(ppc host)(4)");
659 
660    /* Compute off into a reg, %off.  Then return:
661 
662          addi %tmp, %off, bias (if bias != 0)
663          andi %tmp, nElems-1
664          sldi %tmp, shift
665          addi %tmp, %tmp, base
666          ... Baseblockptr + %tmp ...
667    */
668    roff = iselWordExpr_R(env, off, IEndianess);
669    rtmp = newVRegI(env);
670    addInstr(env, PPCInstr_Alu(
671                     Palu_ADD,
672                     rtmp, roff,
673                     PPCRH_Imm(True/*signed*/, toUShort(bias))));
674    addInstr(env, PPCInstr_Alu(
675                     Palu_AND,
676                     rtmp, rtmp,
677                     PPCRH_Imm(False/*unsigned*/, toUShort(nElems-1))));
678    addInstr(env, PPCInstr_Shft(
679                     Pshft_SHL,
680                     env->mode64 ? False : True/*F:64-bit, T:32-bit shift*/,
681                     rtmp, rtmp,
682                     PPCRH_Imm(False/*unsigned*/, toUShort(shift))));
683    addInstr(env, PPCInstr_Alu(
684                     Palu_ADD,
685                     rtmp, rtmp,
686                     PPCRH_Imm(True/*signed*/, toUShort(descr->base))));
687    return
688       PPCAMode_RR( GuestStatePtr(env->mode64), rtmp );
689 }
690 
691 
692 /*---------------------------------------------------------*/
693 /*--- ISEL: Function call helpers                       ---*/
694 /*---------------------------------------------------------*/
695 
696 /* Used only in doHelperCall.  See big comment in doHelperCall re
697    handling of register-parameter args.  This function figures out
698    whether evaluation of an expression might require use of a fixed
699    register.  If in doubt return True (safe but suboptimal).
700 */
701 static
mightRequireFixedRegs(IRExpr * e)702 Bool mightRequireFixedRegs ( IRExpr* e )
703 {
704    switch (e->tag) {
705    case Iex_RdTmp: case Iex_Const: case Iex_Get:
706       return False;
707    default:
708       return True;
709    }
710 }
711 
712 
713 /* Do a complete function call.  |guard| is a Ity_Bit expression
714    indicating whether or not the call happens.  If guard==NULL, the
715    call is unconditional.  |retloc| is set to indicate where the
716    return value is after the call.  The caller (of this fn) must
717    generate code to add |stackAdjustAfterCall| to the stack pointer
718    after the call is done. */
719 
720 static
doHelperCall(UInt * stackAdjustAfterCall,RetLoc * retloc,ISelEnv * env,IRExpr * guard,IRCallee * cee,IRType retTy,IRExpr ** args,IREndness IEndianess)721 void doHelperCall ( /*OUT*/UInt*   stackAdjustAfterCall,
722                     /*OUT*/RetLoc* retloc,
723                     ISelEnv* env,
724                     IRExpr* guard,
725                     IRCallee* cee, IRType retTy, IRExpr** args,
726                     IREndness IEndianess)
727 {
728    PPCCondCode cc;
729    HReg        argregs[PPC_N_REGPARMS];
730    HReg        tmpregs[PPC_N_REGPARMS];
731    Bool        go_fast;
732    Int         n_args, i, argreg;
733    UInt        argiregs;
734    Bool        mode64 = env->mode64;
735 
736    /* Set default returns.  We'll update them later if needed. */
737    *stackAdjustAfterCall = 0;
738    *retloc               = mk_RetLoc_INVALID();
739 
740    /* These are used for cross-checking that IR-level constraints on
741       the use of IRExpr_VECRET() and IRExpr_GSPTR() are observed. */
742    UInt nVECRETs = 0;
743    UInt nGSPTRs  = 0;
744 
745    /* Marshal args for a call and do the call.
746 
747       This function only deals with a tiny set of possibilities, which
748       cover all helpers in practice.  The restrictions are that only
749       arguments in registers are supported, hence only PPC_N_REGPARMS x
750       (mode32:32 | mode64:64) integer bits in total can be passed.
751       In fact the only supported arg type is (mode32:I32 | mode64:I64).
752 
753       The return type can be I{64,32,16,8} or V{128,256}.  In the
754       latter two cases, it is expected that |args| will contain the
755       special node IRExpr_VECRET(), in which case this routine
756       generates code to allocate space on the stack for the vector
757       return value.  Since we are not passing any scalars on the
758       stack, it is enough to preallocate the return space before
759       marshalling any arguments, in this case.
760 
761       |args| may also contain IRExpr_GSPTR(), in which case the value
762       in the guest state pointer register is passed as the
763       corresponding argument.
764 
765       Generating code which is both efficient and correct when
766       parameters are to be passed in registers is difficult, for the
767       reasons elaborated in detail in comments attached to
768       doHelperCall() in priv/host-x86/isel.c.  Here, we use a variant
769       of the method described in those comments.
770 
771       The problem is split into two cases: the fast scheme and the
772       slow scheme.  In the fast scheme, arguments are computed
773       directly into the target (real) registers.  This is only safe
774       when we can be sure that computation of each argument will not
775       trash any real registers set by computation of any other
776       argument.
777 
778       In the slow scheme, all args are first computed into vregs, and
779       once they are all done, they are moved to the relevant real
780       regs.  This always gives correct code, but it also gives a bunch
781       of vreg-to-rreg moves which are usually redundant but are hard
782       for the register allocator to get rid of.
783 
784       To decide which scheme to use, all argument expressions are
785       first examined.  If they are all so simple that it is clear they
786       will be evaluated without use of any fixed registers, use the
787       fast scheme, else use the slow scheme.  Note also that only
788       unconditional calls may use the fast scheme, since having to
789       compute a condition expression could itself trash real
790       registers.
791 
792       Note this requires being able to examine an expression and
793       determine whether or not evaluation of it might use a fixed
794       register.  That requires knowledge of how the rest of this insn
795       selector works.  Currently just the following 3 are regarded as
796       safe -- hopefully they cover the majority of arguments in
797       practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
798    */
799 
800    /* Note that the cee->regparms field is meaningless on PPC32/64 host
801       (since there is only one calling convention) and so we always
802       ignore it. */
803 
804    n_args = 0;
805    for (i = 0; args[i]; i++)
806       n_args++;
807 
808    if (n_args > PPC_N_REGPARMS) {
809       vpanic("doHelperCall(PPC): cannot currently handle > 8 args");
810       // PPC_N_REGPARMS
811    }
812 
813    /* This is kind of stupid .. the arrays are sized as PPC_N_REGPARMS
814       but we then assume that that value is 8. */
815    vassert(PPC_N_REGPARMS == 8);
816 
817    argregs[0] = hregPPC_GPR3(mode64);
818    argregs[1] = hregPPC_GPR4(mode64);
819    argregs[2] = hregPPC_GPR5(mode64);
820    argregs[3] = hregPPC_GPR6(mode64);
821    argregs[4] = hregPPC_GPR7(mode64);
822    argregs[5] = hregPPC_GPR8(mode64);
823    argregs[6] = hregPPC_GPR9(mode64);
824    argregs[7] = hregPPC_GPR10(mode64);
825    argiregs = 0;
826 
827    tmpregs[0] = tmpregs[1] = tmpregs[2] =
828    tmpregs[3] = tmpregs[4] = tmpregs[5] =
829    tmpregs[6] = tmpregs[7] = INVALID_HREG;
830 
831    /* First decide which scheme (slow or fast) is to be used.  First
832       assume the fast scheme, and select slow if any contraindications
833       (wow) appear. */
834 
835    go_fast = True;
836 
837    /* We'll need space on the stack for the return value.  Avoid
838       possible complications with nested calls by using the slow
839       scheme. */
840    if (retTy == Ity_V128 || retTy == Ity_V256)
841       go_fast = False;
842 
843    if (go_fast && guard) {
844       if (guard->tag == Iex_Const
845           && guard->Iex.Const.con->tag == Ico_U1
846           && guard->Iex.Const.con->Ico.U1 == True) {
847          /* unconditional */
848       } else {
849          /* Not manifestly unconditional -- be conservative. */
850          go_fast = False;
851       }
852    }
853 
854    if (go_fast) {
855       for (i = 0; i < n_args; i++) {
856          IRExpr* arg = args[i];
857          if (UNLIKELY(arg->tag == Iex_GSPTR)) {
858             /* that's OK */
859          }
860          else if (UNLIKELY(arg->tag == Iex_VECRET)) {
861             /* This implies ill-formed IR, since if the IR was
862                well-formed, the return-type test above would have
863                filtered it out. */
864             vpanic("doHelperCall(PPC): invalid IR");
865          }
866          else if (mightRequireFixedRegs(arg)) {
867             go_fast = False;
868             break;
869          }
870       }
871    }
872 
873    /* At this point the scheme to use has been established.  Generate
874       code to get the arg values into the argument rregs. */
875 
876    if (go_fast) {
877 
878       /* FAST SCHEME */
879       argreg = 0;
880 
881       for (i = 0; i < n_args; i++) {
882          IRExpr* arg = args[i];
883          vassert(argreg < PPC_N_REGPARMS);
884 
885          if (arg->tag == Iex_GSPTR) {
886             argiregs |= (1 << (argreg+3));
887             addInstr(env, mk_iMOVds_RR( argregs[argreg],
888                                         GuestStatePtr(mode64) ));
889             argreg++;
890          } else {
891             vassert(arg->tag != Iex_VECRET);
892             IRType ty = typeOfIRExpr(env->type_env, arg);
893             vassert(ty == Ity_I32 || ty == Ity_I64);
894             if (!mode64) {
895                if (ty == Ity_I32) {
896                   argiregs |= (1 << (argreg+3));
897                   addInstr(env,
898                            mk_iMOVds_RR( argregs[argreg],
899                                          iselWordExpr_R(env, arg,
900 							IEndianess) ));
901                } else { // Ity_I64 in 32-bit mode
902                   HReg rHi, rLo;
903                   if ((argreg%2) == 1)
904                                  // ppc32 ELF abi spec for passing LONG_LONG
905                      argreg++;   // XXX: odd argreg => even rN
906                   vassert(argreg < PPC_N_REGPARMS-1);
907                   iselInt64Expr(&rHi,&rLo, env, arg, IEndianess);
908                   argiregs |= (1 << (argreg+3));
909                   addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));
910                   argiregs |= (1 << (argreg+3));
911                   addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));
912                }
913             } else { // mode64
914                argiregs |= (1 << (argreg+3));
915                addInstr(env, mk_iMOVds_RR( argregs[argreg],
916                                            iselWordExpr_R(env, arg,
917                                                           IEndianess) ));
918             }
919             argreg++;
920          } /* if (arg == IRExprP__BBPR) */
921       }
922 
923       /* Fast scheme only applies for unconditional calls.  Hence: */
924       cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
925 
926    } else {
927 
928       /* SLOW SCHEME; move via temporaries */
929       argreg = 0;
930 
931       /* If we have a vector return type, allocate a place for it on
932          the stack and record its address.  Rather than figure out the
933          complexities of PPC{32,64} ELF ABI stack frame layout, simply
934          drop the SP by 1024 and allocate the return point in the
935          middle.  I think this should comfortably clear any ABI
936          mandated register save areas.  Note that it doesn't maintain
937          the backchain as it should, since we're not doing st{d,w}u to
938          adjust the SP, but .. that doesn't seem to be a big deal.
939          Since we're not expecting to have to unwind out of here. */
940       HReg r_vecRetAddr = INVALID_HREG;
941       if (retTy == Ity_V128) {
942          r_vecRetAddr = newVRegI(env);
943          sub_from_sp(env, 512);
944          addInstr(env, mk_iMOVds_RR( r_vecRetAddr, StackFramePtr(mode64) ));
945          sub_from_sp(env, 512);
946       }
947       else if (retTy == Ity_V256) {
948          vassert(0); //ATC
949          r_vecRetAddr = newVRegI(env);
950          sub_from_sp(env, 512);
951          addInstr(env, mk_iMOVds_RR( r_vecRetAddr, StackFramePtr(mode64) ));
952          sub_from_sp(env, 512);
953       }
954 
955       vassert(n_args >= 0 && n_args <= 8);
956       for (i = 0; i < n_args; i++) {
957          IRExpr* arg = args[i];
958          vassert(argreg < PPC_N_REGPARMS);
959          if (UNLIKELY(arg->tag == Iex_GSPTR)) {
960             tmpregs[argreg] = newVRegI(env);
961             addInstr(env, mk_iMOVds_RR( tmpregs[argreg],
962                                         GuestStatePtr(mode64) ));
963             nGSPTRs++;
964          }
965          else if (UNLIKELY(arg->tag == Iex_VECRET)) {
966             /* We stashed the address of the return slot earlier, so just
967                retrieve it now. */
968             vassert(!hregIsInvalid(r_vecRetAddr));
969             tmpregs[i] = r_vecRetAddr;
970             nVECRETs++;
971          }
972          else {
973             IRType ty = typeOfIRExpr(env->type_env, arg);
974             vassert(ty == Ity_I32 || ty == Ity_I64);
975             if (!mode64) {
976                if (ty == Ity_I32) {
977                   tmpregs[argreg] = iselWordExpr_R(env, arg, IEndianess);
978                } else { // Ity_I64 in 32-bit mode
979                   HReg rHi, rLo;
980                   if ((argreg%2) == 1)
981                                 // ppc32 ELF abi spec for passing LONG_LONG
982                      argreg++;  // XXX: odd argreg => even rN
983                   vassert(argreg < PPC_N_REGPARMS-1);
984                   iselInt64Expr(&rHi,&rLo, env, arg, IEndianess);
985                   tmpregs[argreg++] = rHi;
986                   tmpregs[argreg]   = rLo;
987                }
988             } else { // mode64
989                tmpregs[argreg] = iselWordExpr_R(env, arg, IEndianess);
990             }
991          }
992          argreg++;
993       }
994 
995       /* Now we can compute the condition.  We can't do it earlier
996          because the argument computations could trash the condition
997          codes.  Be a bit clever to handle the common case where the
998          guard is 1:Bit. */
999       cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
1000       if (guard) {
1001          if (guard->tag == Iex_Const
1002              && guard->Iex.Const.con->tag == Ico_U1
1003              && guard->Iex.Const.con->Ico.U1 == True) {
1004             /* unconditional -- do nothing */
1005          } else {
1006             cc = iselCondCode( env, guard, IEndianess );
1007          }
1008       }
1009 
1010       /* Move the args to their final destinations. */
1011       for (i = 0; i < argreg; i++) {
1012          if (hregIsInvalid(tmpregs[i]))  // Skip invalid regs
1013             continue;
1014          /* None of these insns, including any spill code that might
1015             be generated, may alter the condition codes. */
1016          argiregs |= (1 << (i+3));
1017          addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) );
1018       }
1019 
1020    }
1021 
1022    /* Do final checks, set the return values, and generate the call
1023       instruction proper. */
1024    if (retTy == Ity_V128 || retTy == Ity_V256) {
1025       vassert(nVECRETs == 1);
1026    } else {
1027       vassert(nVECRETs == 0);
1028    }
1029 
1030    vassert(nGSPTRs == 0 || nGSPTRs == 1);
1031 
1032    vassert(*stackAdjustAfterCall == 0);
1033    vassert(is_RetLoc_INVALID(*retloc));
1034    switch (retTy) {
1035       case Ity_INVALID:
1036          /* Function doesn't return a value. */
1037          *retloc = mk_RetLoc_simple(RLPri_None);
1038          break;
1039       case Ity_I64:
1040          *retloc = mk_RetLoc_simple(mode64 ? RLPri_Int : RLPri_2Int);
1041          break;
1042       case Ity_I32: case Ity_I16: case Ity_I8:
1043          *retloc = mk_RetLoc_simple(RLPri_Int);
1044          break;
1045       case Ity_V128:
1046          /* Result is 512 bytes up the stack, and after it has been
1047             retrieved, adjust SP upwards by 1024. */
1048          *retloc = mk_RetLoc_spRel(RLPri_V128SpRel, 512);
1049          *stackAdjustAfterCall = 1024;
1050          break;
1051       case Ity_V256:
1052          vassert(0); // ATC
1053          /* Ditto */
1054          *retloc = mk_RetLoc_spRel(RLPri_V256SpRel, 512);
1055          *stackAdjustAfterCall = 1024;
1056          break;
1057       default:
1058          /* IR can denote other possible return types, but we don't
1059             handle those here. */
1060          vassert(0);
1061    }
1062 
1063    /* Finally, generate the call itself.  This needs the *retloc value
1064       set in the switch above, which is why it's at the end. */
1065 
1066    Addr64 target = mode64 ? (Addr)cee->addr
1067                           : toUInt((Addr)(cee->addr));
1068    addInstr(env, PPCInstr_Call( cc, target, argiregs, *retloc ));
1069 }
1070 
1071 
1072 /*---------------------------------------------------------*/
1073 /*--- ISEL: FP rounding mode helpers                    ---*/
1074 /*---------------------------------------------------------*/
1075 
1076 ///* Set FPU's rounding mode to the default */
1077 //static
1078 //void set_FPU_rounding_default ( ISelEnv* env )
1079 //{
1080 //   HReg fr_src = newVRegF(env);
1081 //   HReg r_src  = newVRegI(env);
1082 //
1083 //   /* Default rounding mode = 0x0
1084 //      Only supporting the rounding-mode bits - the rest of FPSCR is 0x0
1085 //       - so we can set the whole register at once (faster)
1086 //      note: upper 32 bits ignored by FpLdFPSCR
1087 //   */
1088 //   addInstr(env, PPCInstr_LI(r_src, 0x0, env->mode64));
1089 //   if (env->mode64) {
1090 //      fr_src = mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
1091 //   } else {
1092 //      fr_src = mk_LoadRR32toFPR( env, r_src, r_src ); // 2*I32 -> F64
1093 //   }
1094 //   addInstr(env, PPCInstr_FpLdFPSCR( fr_src ));
1095 //}
1096 
1097 /* Convert IR rounding mode to PPC encoding */
roundModeIRtoPPC(ISelEnv * env,HReg r_rmIR)1098 static HReg roundModeIRtoPPC ( ISelEnv* env, HReg r_rmIR )
1099 {
1100    /*
1101    rounding mode                     | PPC  |  IR
1102    -----------------------------------------------
1103    to nearest, ties to even          | 000  | 000
1104    to zero                           | 001  | 011
1105    to +infinity                      | 010  | 010
1106    to -infinity                      | 011  | 001
1107    +++++ Below are the extended rounding modes for decimal floating point +++++
1108    to nearest, ties away from 0      | 100  | 100
1109    to nearest, ties toward 0         | 101  | 111
1110    to away from 0                    | 110  | 110
1111    to prepare for shorter precision  | 111  | 101
1112    */
1113    HReg r_rmPPC = newVRegI(env);
1114    HReg r_tmp1  = newVRegI(env);
1115    HReg r_tmp2  = newVRegI(env);
1116 
1117    vassert(hregClass(r_rmIR) == HRcGPR(env->mode64));
1118 
1119    // r_rmPPC = XOR(r_rmIR, r_rmIR << 1) & 3
1120    //
1121    // slwi  tmp1,    r_rmIR, 1
1122    // xor   tmp1,    r_rmIR, tmp1
1123    // andi  r_rmPPC, tmp1, 3
1124 
1125    addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1126                                r_tmp1, r_rmIR, PPCRH_Imm(False,1)));
1127 
1128    addInstr( env, PPCInstr_Alu( Palu_AND,
1129                                 r_tmp2, r_tmp1, PPCRH_Imm( False, 3 ) ) );
1130 
1131    addInstr( env, PPCInstr_Alu( Palu_XOR,
1132                                 r_rmPPC, r_rmIR, PPCRH_Reg( r_tmp2 ) ) );
1133 
1134    return r_rmPPC;
1135 }
1136 
1137 
1138 /* Set the FPU's rounding mode: 'mode' is an I32-typed expression
1139    denoting a value in the range 0 .. 7, indicating a round mode
1140    encoded as per type IRRoundingMode.  Set the PPC FPSCR to have the
1141    same rounding.  When the dfp_rm arg is True, set the decimal
1142    floating point rounding mode bits (29:31); otherwise, set the
1143    binary floating point rounding mode bits (62:63).
1144 
1145    For speed & simplicity, we're setting the *entire* FPSCR here.
1146 
1147    Setting the rounding mode is expensive.  So this function tries to
1148    avoid repeatedly setting the rounding mode to the same thing by
1149    first comparing 'mode' to the 'mode' tree supplied in the previous
1150    call to this function, if any.  (The previous value is stored in
1151    env->previous_rm.)  If 'mode' is a single IR temporary 't' and
1152    env->previous_rm is also just 't', then the setting is skipped.
1153 
1154    This is safe because of the SSA property of IR: an IR temporary can
1155    only be defined once and so will have the same value regardless of
1156    where it appears in the block.  Cool stuff, SSA.
1157 
1158    A safety condition: all attempts to set the RM must be aware of
1159    this mechanism - by being routed through the functions here.
1160 
1161    Of course this only helps if blocks where the RM is set more than
1162    once and it is set to the same value each time, *and* that value is
1163    held in the same IR temporary each time.  In order to assure the
1164    latter as much as possible, the IR optimiser takes care to do CSE
1165    on any block with any sign of floating point activity.
1166 */
1167 static
_set_FPU_rounding_mode(ISelEnv * env,IRExpr * mode,Bool dfp_rm,IREndness IEndianess)1168 void _set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode, Bool dfp_rm,
1169                               IREndness IEndianess )
1170 {
1171    HReg fr_src = newVRegF(env);
1172    HReg r_src;
1173 
1174    vassert(typeOfIRExpr(env->type_env,mode) == Ity_I32);
1175 
1176    /* Do we need to do anything? */
1177    if (env->previous_rm
1178        && env->previous_rm->tag == Iex_RdTmp
1179        && mode->tag == Iex_RdTmp
1180        && env->previous_rm->Iex.RdTmp.tmp == mode->Iex.RdTmp.tmp) {
1181       /* no - setting it to what it was before.  */
1182       vassert(typeOfIRExpr(env->type_env, env->previous_rm) == Ity_I32);
1183       return;
1184    }
1185 
1186    /* No luck - we better set it, and remember what we set it to. */
1187    env->previous_rm = mode;
1188 
1189    /* Only supporting the rounding-mode bits - the rest of FPSCR is
1190       0x0 - so we can set the whole register at once (faster). */
1191 
1192    // Resolve rounding mode and convert to PPC representation
1193    r_src = roundModeIRtoPPC( env, iselWordExpr_R(env, mode, IEndianess) );
1194 
1195    // gpr -> fpr
1196    if (env->mode64) {
1197       if (dfp_rm) {
1198          HReg r_tmp1 = newVRegI( env );
1199          addInstr( env,
1200                    PPCInstr_Shft( Pshft_SHL, False/*64bit shift*/,
1201                                   r_tmp1, r_src, PPCRH_Imm( False, 32 ) ) );
1202          fr_src = mk_LoadR64toFPR( env, r_tmp1 );
1203       } else {
1204          fr_src = mk_LoadR64toFPR( env, r_src ); // 1*I64 -> F64
1205       }
1206    } else {
1207       if (dfp_rm) {
1208          HReg r_zero = newVRegI( env );
1209          addInstr( env, PPCInstr_LI( r_zero, 0, env->mode64 ) );
1210          fr_src = mk_LoadRR32toFPR( env, r_src, r_zero );
1211       } else {
1212          fr_src = mk_LoadRR32toFPR( env, r_src, r_src ); // 2*I32 -> F64
1213       }
1214    }
1215 
1216    // Move to FPSCR
1217    addInstr(env, PPCInstr_FpLdFPSCR( fr_src, dfp_rm ));
1218 }
1219 
set_FPU_rounding_mode(ISelEnv * env,IRExpr * mode,IREndness IEndianess)1220 static void set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode,
1221                                     IREndness IEndianess )
1222 {
1223    _set_FPU_rounding_mode(env, mode, False, IEndianess);
1224 }
1225 
set_FPU_DFP_rounding_mode(ISelEnv * env,IRExpr * mode,IREndness IEndianess)1226 static void set_FPU_DFP_rounding_mode ( ISelEnv* env, IRExpr* mode,
1227                                         IREndness IEndianess )
1228 {
1229    _set_FPU_rounding_mode(env, mode, True, IEndianess);
1230 }
1231 
1232 static
FPU_rounding_mode_isOdd(IRExpr * mode)1233 Bool FPU_rounding_mode_isOdd (IRExpr* mode) {
1234    /* If the rounding mode is set to odd, the the expr must be a constant U8
1235     * value equal to 8.  Otherwise, it must be a bin op expressiong that
1236     * calculates the value.
1237     */
1238 
1239    if (mode->tag != Iex_Const)
1240       return False;
1241 
1242    vassert(mode->Iex.Const.con->tag == Ico_U32);
1243    vassert(mode->Iex.Const.con->Ico.U32 == 0x8);
1244    return True;
1245 }
1246 
1247 /*---------------------------------------------------------*/
1248 /*--- ISEL: vector helpers                              ---*/
1249 /*---------------------------------------------------------*/
1250 
1251 /* Generate all-zeroes into a new vector register.
1252 */
generate_zeroes_V128(ISelEnv * env)1253 static HReg generate_zeroes_V128 ( ISelEnv* env )
1254 {
1255    HReg dst = newVRegV(env);
1256    addInstr(env, PPCInstr_AvBinary(Pav_XOR, dst, dst, dst));
1257    return dst;
1258 }
1259 
1260 /* Generate all-ones into a new vector register.
1261 */
generate_ones_V128(ISelEnv * env)1262 static HReg generate_ones_V128 ( ISelEnv* env )
1263 {
1264    HReg dst = newVRegV(env);
1265    PPCVI5s * src = PPCVI5s_Imm(-1);
1266    addInstr(env, PPCInstr_AvSplat(8, dst, src));
1267    return dst;
1268 }
1269 
1270 
1271 /*
1272   Generates code for AvSplat
1273   - takes in IRExpr* of type 8|16|32
1274     returns vector reg of duplicated lanes of input
1275   - uses AvSplat(imm) for imms up to simm6.
1276     otherwise must use store reg & load vector
1277 */
mk_AvDuplicateRI(ISelEnv * env,IRExpr * e,IREndness IEndianess)1278 static HReg mk_AvDuplicateRI( ISelEnv* env, IRExpr* e, IREndness IEndianess )
1279 {
1280    HReg   r_src;
1281    HReg   dst = newVRegV(env);
1282    PPCRI* ri  = iselWordExpr_RI(env, e, IEndianess);
1283    IRType ty  = typeOfIRExpr(env->type_env,e);
1284    UInt   sz  = (ty == Ity_I8) ? 8 : (ty == Ity_I16) ? 16 : 32;
1285    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
1286 
1287    /* special case: immediate */
1288    if (ri->tag == Pri_Imm) {
1289       Int simm32 = (Int)ri->Pri.Imm;
1290 
1291       /* figure out if it's do-able with imm splats. */
1292       if (simm32 >= -32 && simm32 <= 31) {
1293          Char simm6 = (Char)simm32;
1294          if (simm6 > 15) {           /* 16:31 inclusive */
1295             HReg v1 = newVRegV(env);
1296             HReg v2 = newVRegV(env);
1297             addInstr(env, PPCInstr_AvSplat(sz, v1, PPCVI5s_Imm(-16)));
1298             addInstr(env, PPCInstr_AvSplat(sz, v2, PPCVI5s_Imm(simm6-16)));
1299             addInstr(env,
1300                (sz== 8) ? PPCInstr_AvBin8x16(Pav_SUBU, dst, v2, v1) :
1301                (sz==16) ? PPCInstr_AvBin16x8(Pav_SUBU, dst, v2, v1)
1302                         : PPCInstr_AvBin32x4(Pav_SUBU, dst, v2, v1) );
1303             return dst;
1304          }
1305          if (simm6 < -16) {          /* -32:-17 inclusive */
1306             HReg v1 = newVRegV(env);
1307             HReg v2 = newVRegV(env);
1308             addInstr(env, PPCInstr_AvSplat(sz, v1, PPCVI5s_Imm(-16)));
1309             addInstr(env, PPCInstr_AvSplat(sz, v2, PPCVI5s_Imm(simm6+16)));
1310             addInstr(env,
1311                (sz== 8) ? PPCInstr_AvBin8x16(Pav_ADDU, dst, v2, v1) :
1312                (sz==16) ? PPCInstr_AvBin16x8(Pav_ADDU, dst, v2, v1)
1313                         : PPCInstr_AvBin32x4(Pav_ADDU, dst, v2, v1) );
1314             return dst;
1315          }
1316          /* simplest form:              -16:15 inclusive */
1317          addInstr(env, PPCInstr_AvSplat(sz, dst, PPCVI5s_Imm(simm6)));
1318          return dst;
1319       }
1320 
1321       /* no luck; use the Slow way. */
1322       r_src = newVRegI(env);
1323       addInstr(env, PPCInstr_LI(r_src, (Long)simm32, env->mode64));
1324    }
1325    else {
1326       r_src = ri->Pri.Reg;
1327    }
1328 
1329    {
1330       /* Store r_src multiple times (sz dependent); then load the dest vector. */
1331       HReg r_aligned16;
1332       PPCAMode *am_offset, *am_offset_zero;
1333 
1334       sub_from_sp( env, 32 );     // Move SP down
1335       /* Get a 16-aligned address within our stack space */
1336       r_aligned16 = get_sp_aligned16( env );
1337 
1338       Int i;
1339       Int stride = (sz == 8) ? 1 : (sz == 16) ? 2 : 4;
1340       UChar num_bytes_to_store = stride;
1341       am_offset_zero = PPCAMode_IR( 0, r_aligned16 );
1342       am_offset = am_offset_zero;
1343       for (i = 0; i < 16; i+=stride, am_offset = PPCAMode_IR( i, r_aligned16)) {
1344          addInstr(env, PPCInstr_Store( num_bytes_to_store, am_offset, r_src, env->mode64 ));
1345       }
1346 
1347       /* Effectively splat the r_src value to dst */
1348       addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 16, dst, am_offset_zero ) );
1349       add_to_sp( env, 32 );       // Reset SP
1350 
1351       return dst;
1352    }
1353 }
1354 
1355 
1356 /* for each lane of vSrc: lane == nan ? laneX = all 1's : all 0's */
isNan(ISelEnv * env,HReg vSrc,IREndness IEndianess)1357 static HReg isNan ( ISelEnv* env, HReg vSrc, IREndness IEndianess )
1358 {
1359    HReg zeros, msk_exp, msk_mnt, expt, mnts, vIsNan;
1360 
1361    vassert(hregClass(vSrc) == HRcVec128);
1362 
1363    zeros   = mk_AvDuplicateRI(env, mkU32(0), IEndianess);
1364    msk_exp = mk_AvDuplicateRI(env, mkU32(0x7F800000), IEndianess);
1365    msk_mnt = mk_AvDuplicateRI(env, mkU32(0x7FFFFF), IEndianess);
1366    expt    = newVRegV(env);
1367    mnts    = newVRegV(env);
1368    vIsNan  = newVRegV(env);
1369 
1370    /* 32bit float => sign(1) | exponent(8) | mantissa(23)
1371       nan => exponent all ones, mantissa > 0 */
1372 
1373    addInstr(env, PPCInstr_AvBinary(Pav_AND, expt, vSrc, msk_exp));
1374    addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, expt, expt, msk_exp));
1375    addInstr(env, PPCInstr_AvBinary(Pav_AND, mnts, vSrc, msk_mnt));
1376    addInstr(env, PPCInstr_AvBin32x4(Pav_CMPGTU, mnts, mnts, zeros));
1377    addInstr(env, PPCInstr_AvBinary(Pav_AND, vIsNan, expt, mnts));
1378    return vIsNan;
1379 }
1380 
1381 
1382 /*---------------------------------------------------------*/
1383 /*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
1384 /*---------------------------------------------------------*/
1385 
1386 /* Select insns for an integer-typed expression, and add them to the
1387    code list.  Return a reg holding the result.  This reg will be a
1388    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
1389    want to modify it, ask for a new vreg, copy it in there, and modify
1390    the copy.  The register allocator will do its best to map both
1391    vregs to the same real register, so the copies will often disappear
1392    later in the game.
1393 
1394    This should handle expressions of 64, 32, 16 and 8-bit type.
1395    All results are returned in a (mode64 ? 64bit : 32bit) register.
1396    For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
1397    are arbitrary, so you should mask or sign extend partial values
1398    if necessary.
1399 */
1400 
iselWordExpr_R(ISelEnv * env,const IRExpr * e,IREndness IEndianess)1401 static HReg iselWordExpr_R ( ISelEnv* env, const IRExpr* e,
1402                              IREndness IEndianess )
1403 {
1404    HReg r = iselWordExpr_R_wrk(env, e, IEndianess);
1405    /* sanity checks ... */
1406 #  if 0
1407    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
1408 #  endif
1409 
1410    vassert(hregClass(r) == HRcGPR(env->mode64));
1411    vassert(hregIsVirtual(r));
1412    return r;
1413 }
1414 
1415 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_R_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)1416 static HReg iselWordExpr_R_wrk ( ISelEnv* env, const IRExpr* e,
1417                                  IREndness IEndianess )
1418 {
1419    Bool mode64 = env->mode64;
1420    MatchInfo mi;
1421    DECLARE_PATTERN(p_32to1_then_1Uto8);
1422 
1423    IRType ty = typeOfIRExpr(env->type_env,e);
1424    vassert(ty == Ity_I8 || ty == Ity_I16 ||
1425            ty == Ity_I32 || ((ty == Ity_I64) && mode64));
1426 
1427    switch (e->tag) {
1428 
1429    /* --------- TEMP --------- */
1430    case Iex_RdTmp:
1431       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
1432 
1433    /* --------- LOAD --------- */
1434    case Iex_Load: {
1435       HReg      r_dst;
1436       PPCAMode* am_addr;
1437       if (e->Iex.Load.end != IEndianess)
1438          goto irreducible;
1439       r_dst   = newVRegI(env);
1440       am_addr = iselWordExpr_AMode( env, e->Iex.Load.addr, ty/*of xfer*/,
1441                                     IEndianess );
1442       addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
1443                                    r_dst, am_addr, mode64 ));
1444       return r_dst;
1445       /*NOTREACHED*/
1446    }
1447 
1448    /* --------- BINARY OP --------- */
1449    case Iex_Binop: {
1450       PPCAluOp  aluOp;
1451       PPCShftOp shftOp;
1452 
1453       /* Is it an addition or logical style op? */
1454       switch (e->Iex.Binop.op) {
1455       case Iop_Add8: case Iop_Add16: case Iop_Add32: case Iop_Add64:
1456          aluOp = Palu_ADD; break;
1457       case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: case Iop_Sub64:
1458          aluOp = Palu_SUB; break;
1459       case Iop_And8: case Iop_And16: case Iop_And32: case Iop_And64:
1460          aluOp = Palu_AND; break;
1461       case Iop_Or8:  case Iop_Or16:  case Iop_Or32:  case Iop_Or64:
1462          aluOp = Palu_OR; break;
1463       case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: case Iop_Xor64:
1464          aluOp = Palu_XOR; break;
1465       default:
1466          aluOp = Palu_INVALID; break;
1467       }
1468       /* For commutative ops we assume any literal
1469          values are on the second operand. */
1470       if (aluOp != Palu_INVALID) {
1471          HReg   r_dst   = newVRegI(env);
1472          HReg   r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1473          PPCRH* ri_srcR = NULL;
1474          /* get right arg into an RH, in the appropriate way */
1475          switch (aluOp) {
1476          case Palu_ADD: case Palu_SUB:
1477             ri_srcR = iselWordExpr_RH(env, True/*signed*/,
1478                                       e->Iex.Binop.arg2, IEndianess);
1479             break;
1480          case Palu_AND: case Palu_OR: case Palu_XOR:
1481             ri_srcR = iselWordExpr_RH(env, False/*signed*/,
1482                                       e->Iex.Binop.arg2, IEndianess);
1483             break;
1484          default:
1485             vpanic("iselWordExpr_R_wrk-aluOp-arg2");
1486          }
1487          addInstr(env, PPCInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
1488          return r_dst;
1489       }
1490 
1491       /* a shift? */
1492       switch (e->Iex.Binop.op) {
1493       case Iop_Shl8: case Iop_Shl16: case Iop_Shl32: case Iop_Shl64:
1494          shftOp = Pshft_SHL; break;
1495       case Iop_Shr8: case Iop_Shr16: case Iop_Shr32: case Iop_Shr64:
1496          shftOp = Pshft_SHR; break;
1497       case Iop_Sar8: case Iop_Sar16: case Iop_Sar32: case Iop_Sar64:
1498          shftOp = Pshft_SAR; break;
1499       default:
1500          shftOp = Pshft_INVALID; break;
1501       }
1502       /* we assume any literal values are on the second operand. */
1503       if (shftOp != Pshft_INVALID) {
1504          HReg   r_dst   = newVRegI(env);
1505          HReg   r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1506          PPCRH* ri_srcR = NULL;
1507          /* get right arg into an RH, in the appropriate way */
1508          switch (shftOp) {
1509          case Pshft_SHL: case Pshft_SHR: case Pshft_SAR:
1510             if (!mode64)
1511                ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2, IEndianess);
1512             else
1513                ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2, IEndianess);
1514             break;
1515          default:
1516             vpanic("iselIntExpr_R_wrk-shftOp-arg2");
1517          }
1518          /* widen the left arg if needed */
1519          if (shftOp == Pshft_SHR || shftOp == Pshft_SAR) {
1520             if (ty == Ity_I8 || ty == Ity_I16) {
1521                PPCRH* amt = PPCRH_Imm(False,
1522                                       toUShort(ty == Ity_I8 ? 24 : 16));
1523                HReg   tmp = newVRegI(env);
1524                addInstr(env, PPCInstr_Shft(Pshft_SHL,
1525                                            True/*32bit shift*/,
1526                                            tmp, r_srcL, amt));
1527                addInstr(env, PPCInstr_Shft(shftOp,
1528                                            True/*32bit shift*/,
1529                                            tmp, tmp,    amt));
1530                r_srcL = tmp;
1531             }
1532          }
1533          /* Only 64 expressions need 64bit shifts,
1534             32bit shifts are fine for all others */
1535          if (ty == Ity_I64) {
1536             vassert(mode64);
1537             addInstr(env, PPCInstr_Shft(shftOp, False/*64bit shift*/,
1538                                         r_dst, r_srcL, ri_srcR));
1539          } else {
1540             addInstr(env, PPCInstr_Shft(shftOp, True/*32bit shift*/,
1541                                         r_dst, r_srcL, ri_srcR));
1542          }
1543          return r_dst;
1544       }
1545 
1546       /* How about a div? */
1547       if (e->Iex.Binop.op == Iop_DivS32 ||
1548           e->Iex.Binop.op == Iop_DivU32 ||
1549           e->Iex.Binop.op == Iop_DivS32E ||
1550           e->Iex.Binop.op == Iop_DivU32E) {
1551          Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS32) || (e->Iex.Binop.op == Iop_DivS32E));
1552          HReg r_dst  = newVRegI(env);
1553          HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1554          HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1555          addInstr( env,
1556                       PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivU32E )
1557                                              || ( e->Iex.Binop.op == Iop_DivS32E ) ) ? True
1558                                                                                      : False,
1559                                     syned,
1560                                     True/*32bit div*/,
1561                                     r_dst,
1562                                     r_srcL,
1563                                     r_srcR ) );
1564          return r_dst;
1565       }
1566       if (e->Iex.Binop.op == Iop_DivS64 ||
1567           e->Iex.Binop.op == Iop_DivU64 || e->Iex.Binop.op == Iop_DivS64E
1568           || e->Iex.Binop.op == Iop_DivU64E ) {
1569          Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS64) ||(e->Iex.Binop.op == Iop_DivS64E));
1570          HReg r_dst  = newVRegI(env);
1571          HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1572          HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1573          vassert(mode64);
1574          addInstr( env,
1575                       PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivS64E )
1576                                              || ( e->Iex.Binop.op
1577                                                       == Iop_DivU64E ) ) ? True
1578                                                                          : False,
1579                                     syned,
1580                                     False/*64bit div*/,
1581                                     r_dst,
1582                                     r_srcL,
1583                                     r_srcR ) );
1584          return r_dst;
1585       }
1586 
1587       /* No? Anyone for a mul? */
1588       if (e->Iex.Binop.op == Iop_Mul32
1589           || e->Iex.Binop.op == Iop_Mul64) {
1590          Bool syned       = False;
1591          Bool sz32        = (e->Iex.Binop.op != Iop_Mul64);
1592          HReg r_dst       = newVRegI(env);
1593          HReg r_srcL      = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1594          HReg r_srcR      = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1595          addInstr(env, PPCInstr_MulL(syned, False/*lo32*/, sz32,
1596                                      r_dst, r_srcL, r_srcR));
1597          return r_dst;
1598       }
1599 
1600       /* 32 x 32 -> 64 multiply */
1601       if (mode64
1602           && (e->Iex.Binop.op == Iop_MullU32
1603               || e->Iex.Binop.op == Iop_MullS32)) {
1604          HReg tLo    = newVRegI(env);
1605          HReg tHi    = newVRegI(env);
1606          HReg r_dst  = newVRegI(env);
1607          Bool syned  = toBool(e->Iex.Binop.op == Iop_MullS32);
1608          HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1609          HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1610          addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
1611                                      False/*lo32*/, True/*32bit mul*/,
1612                                      tLo, r_srcL, r_srcR));
1613          addInstr(env, PPCInstr_MulL(syned,
1614                                      True/*hi32*/, True/*32bit mul*/,
1615                                      tHi, r_srcL, r_srcR));
1616          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1617                                      r_dst, tHi, PPCRH_Imm(False,32)));
1618          addInstr(env, PPCInstr_Alu(Palu_OR,
1619                                     r_dst, r_dst, PPCRH_Reg(tLo)));
1620          return r_dst;
1621       }
1622 
1623       /* El-mutanto 3-way compare? */
1624       if (e->Iex.Binop.op == Iop_CmpORD32S
1625           || e->Iex.Binop.op == Iop_CmpORD32U) {
1626          Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD32S);
1627          HReg   dst   = newVRegI(env);
1628          HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1629          PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2,
1630                                         IEndianess);
1631          addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
1632                                     7/*cr*/, srcL, srcR));
1633          addInstr(env, PPCInstr_MfCR(dst));
1634          addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1635                                     PPCRH_Imm(False,7<<1)));
1636          return dst;
1637       }
1638 
1639       if (e->Iex.Binop.op == Iop_CmpORD64S
1640           || e->Iex.Binop.op == Iop_CmpORD64U) {
1641          Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD64S);
1642          HReg   dst   = newVRegI(env);
1643          HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1644          PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2,
1645                                         IEndianess);
1646          vassert(mode64);
1647          addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
1648                                     7/*cr*/, srcL, srcR));
1649          addInstr(env, PPCInstr_MfCR(dst));
1650          addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1651                                     PPCRH_Imm(False,7<<1)));
1652          return dst;
1653       }
1654 
1655       if (e->Iex.Binop.op == Iop_Max32U) {
1656          HReg        r1   = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1657          HReg        r2   = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1658          HReg        rdst = newVRegI(env);
1659          PPCCondCode cc   = mk_PPCCondCode( Pct_TRUE, Pcf_7LT );
1660          addInstr(env, mk_iMOVds_RR(rdst, r1));
1661          addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
1662                                     7/*cr*/, rdst, PPCRH_Reg(r2)));
1663          addInstr(env, PPCInstr_CMov(cc, rdst, PPCRI_Reg(r2)));
1664          return rdst;
1665       }
1666 
1667       if (e->Iex.Binop.op == Iop_32HLto64) {
1668          HReg   r_Hi  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1669          HReg   r_Lo  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1670          HReg   r_Tmp = newVRegI(env);
1671          HReg   r_dst = newVRegI(env);
1672          HReg   msk   = newVRegI(env);
1673          vassert(mode64);
1674          /* r_dst = OR( r_Hi<<32, r_Lo ) */
1675          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1676                                      r_dst, r_Hi, PPCRH_Imm(False,32)));
1677          addInstr(env, PPCInstr_LI(msk, 0xFFFFFFFF, mode64));
1678          addInstr(env, PPCInstr_Alu( Palu_AND, r_Tmp, r_Lo,
1679                                      PPCRH_Reg(msk) ));
1680          addInstr(env, PPCInstr_Alu( Palu_OR, r_dst, r_dst,
1681                                      PPCRH_Reg(r_Tmp) ));
1682          return r_dst;
1683       }
1684 
1685       if ((e->Iex.Binop.op == Iop_CmpF64) ||
1686           (e->Iex.Binop.op == Iop_CmpD64) ||
1687           (e->Iex.Binop.op == Iop_CmpD128)) {
1688          HReg fr_srcL;
1689          HReg fr_srcL_lo;
1690          HReg fr_srcR;
1691          HReg fr_srcR_lo;
1692 
1693          HReg r_ccPPC   = newVRegI(env);
1694          HReg r_ccIR    = newVRegI(env);
1695          HReg r_ccIR_b0 = newVRegI(env);
1696          HReg r_ccIR_b2 = newVRegI(env);
1697          HReg r_ccIR_b6 = newVRegI(env);
1698 
1699          if (e->Iex.Binop.op == Iop_CmpF64) {
1700             fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1, IEndianess);
1701             fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
1702             addInstr(env, PPCInstr_FpCmp(r_ccPPC, fr_srcL, fr_srcR));
1703 
1704          } else if (e->Iex.Binop.op == Iop_CmpD64) {
1705             fr_srcL = iselDfp64Expr(env, e->Iex.Binop.arg1, IEndianess);
1706             fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
1707             addInstr(env, PPCInstr_Dfp64Cmp(r_ccPPC, fr_srcL, fr_srcR));
1708 
1709          } else {    //  e->Iex.Binop.op == Iop_CmpD128
1710             iselDfp128Expr(&fr_srcL, &fr_srcL_lo, env, e->Iex.Binop.arg1,
1711                            IEndianess);
1712             iselDfp128Expr(&fr_srcR, &fr_srcR_lo, env, e->Iex.Binop.arg2,
1713                            IEndianess);
1714             addInstr(env, PPCInstr_Dfp128Cmp(r_ccPPC, fr_srcL, fr_srcL_lo,
1715                                              fr_srcR, fr_srcR_lo));
1716          }
1717 
1718          /* Map compare result from PPC to IR,
1719             conforming to CmpF64 definition. */
1720          /*
1721            FP cmp result | PPC | IR
1722            --------------------------
1723            UN            | 0x1 | 0x45
1724            EQ            | 0x2 | 0x40
1725            GT            | 0x4 | 0x00
1726            LT            | 0x8 | 0x01
1727          */
1728 
1729          // r_ccIR_b0 = r_ccPPC[0] | r_ccPPC[3]
1730          addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1731                                      r_ccIR_b0, r_ccPPC,
1732                                      PPCRH_Imm(False,0x3)));
1733          addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b0,
1734                                     r_ccPPC,   PPCRH_Reg(r_ccIR_b0)));
1735          addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b0,
1736                                     r_ccIR_b0, PPCRH_Imm(False,0x1)));
1737 
1738          // r_ccIR_b2 = r_ccPPC[0]
1739          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1740                                      r_ccIR_b2, r_ccPPC,
1741                                      PPCRH_Imm(False,0x2)));
1742          addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b2,
1743                                     r_ccIR_b2, PPCRH_Imm(False,0x4)));
1744 
1745          // r_ccIR_b6 = r_ccPPC[0] | r_ccPPC[1]
1746          addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1747                                      r_ccIR_b6, r_ccPPC,
1748                                      PPCRH_Imm(False,0x1)));
1749          addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b6,
1750                                     r_ccPPC, PPCRH_Reg(r_ccIR_b6)));
1751          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1752                                      r_ccIR_b6, r_ccIR_b6,
1753                                      PPCRH_Imm(False,0x6)));
1754          addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b6,
1755                                     r_ccIR_b6, PPCRH_Imm(False,0x40)));
1756 
1757          // r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6
1758          addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1759                                     r_ccIR_b0, PPCRH_Reg(r_ccIR_b2)));
1760          addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1761                                     r_ccIR,    PPCRH_Reg(r_ccIR_b6)));
1762          return r_ccIR;
1763       }
1764 
1765       if ( e->Iex.Binop.op == Iop_F64toI32S ||
1766                e->Iex.Binop.op == Iop_F64toI32U ) {
1767          /* This works in both mode64 and mode32. */
1768          HReg      r1      = StackFramePtr(env->mode64);
1769          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1770          HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
1771          HReg      ftmp    = newVRegF(env);
1772          HReg      idst    = newVRegI(env);
1773 
1774          /* Set host rounding mode */
1775          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
1776 
1777          sub_from_sp( env, 16 );
1778          addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/,
1779                                        e->Iex.Binop.op == Iop_F64toI32S ? True/*syned*/
1780                                                                      : False,
1781                                        True/*flt64*/,
1782                                        ftmp, fsrc));
1783          addInstr(env, PPCInstr_FpSTFIW(r1, ftmp));
1784          addInstr(env, PPCInstr_Load(4, idst, zero_r1, mode64));
1785 
1786          /* in 64-bit mode we need to sign-widen idst. */
1787          if (mode64)
1788             addInstr(env, PPCInstr_Unary(Pun_EXTSW, idst, idst));
1789 
1790          add_to_sp( env, 16 );
1791 
1792          ///* Restore default FPU rounding. */
1793          //set_FPU_rounding_default( env );
1794          return idst;
1795       }
1796 
1797       if (e->Iex.Binop.op == Iop_F64toI64S || e->Iex.Binop.op == Iop_F64toI64U ) {
1798          if (mode64) {
1799             HReg      r1      = StackFramePtr(env->mode64);
1800             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1801             HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2,
1802                                             IEndianess);
1803             HReg      idst    = newVRegI(env);
1804             HReg      ftmp    = newVRegF(env);
1805 
1806             /* Set host rounding mode */
1807             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
1808 
1809             sub_from_sp( env, 16 );
1810             addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
1811                                           ( e->Iex.Binop.op == Iop_F64toI64S ) ? True
1812                                                                             : False,
1813                                           True, ftmp, fsrc));
1814             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1815             addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
1816             add_to_sp( env, 16 );
1817 
1818             ///* Restore default FPU rounding. */
1819             //set_FPU_rounding_default( env );
1820             return idst;
1821          }
1822       }
1823 
1824       if (e->Iex.Binop.op == Iop_D64toI64S ) {
1825          HReg      r1      = StackFramePtr(env->mode64);
1826          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1827          HReg      fr_src  = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
1828          HReg      idst    = newVRegI(env);
1829          HReg      ftmp    = newVRegF(env);
1830 
1831          /* Set host rounding mode */
1832          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
1833          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTFIX, ftmp, fr_src));
1834          sub_from_sp( env, 16 );
1835          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1836          addInstr(env, PPCInstr_Load(8, idst, zero_r1, mode64));
1837 
1838          add_to_sp( env, 16 );
1839 
1840          ///* Restore default FPU rounding. */
1841          //set_FPU_rounding_default( env );
1842          return idst;
1843       }
1844 
1845       if (e->Iex.Binop.op == Iop_D128toI64S ) {
1846          PPCFpOp fpop = Pfp_DCTFIXQ;
1847          HReg r_srcHi = newVRegF(env);
1848          HReg r_srcLo = newVRegF(env);
1849          HReg idst    = newVRegI(env);
1850          HReg ftmp    = newVRegF(env);
1851          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
1852 
1853          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
1854          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
1855                         IEndianess);
1856          addInstr(env, PPCInstr_DfpD128toD64(fpop, ftmp, r_srcHi, r_srcLo));
1857 
1858          // put the D64 result into an integer register
1859          sub_from_sp( env, 16 );
1860          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1861          addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
1862          add_to_sp( env, 16 );
1863          return idst;
1864       }
1865       break;
1866    }
1867 
1868    /* --------- UNARY OP --------- */
1869    case Iex_Unop: {
1870       IROp op_unop = e->Iex.Unop.op;
1871 
1872       /* 1Uto8(32to1(expr32)) */
1873       DEFINE_PATTERN(p_32to1_then_1Uto8,
1874                      unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
1875       if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
1876          const IRExpr* expr32 = mi.bindee[0];
1877          HReg r_dst = newVRegI(env);
1878          HReg r_src = iselWordExpr_R(env, expr32, IEndianess);
1879          addInstr(env, PPCInstr_Alu(Palu_AND, r_dst,
1880                                     r_src, PPCRH_Imm(False,1)));
1881          return r_dst;
1882       }
1883 
1884       /* 16Uto32(LDbe:I16(expr32)) */
1885       {
1886          DECLARE_PATTERN(p_LDbe16_then_16Uto32);
1887          DEFINE_PATTERN(p_LDbe16_then_16Uto32,
1888                         unop(Iop_16Uto32,
1889                              IRExpr_Load(IEndianess,Ity_I16,bind(0))) );
1890          if (matchIRExpr(&mi,p_LDbe16_then_16Uto32,e)) {
1891             HReg r_dst = newVRegI(env);
1892             PPCAMode* amode
1893                = iselWordExpr_AMode( env, mi.bindee[0], Ity_I16/*xfer*/,
1894                                      IEndianess );
1895             addInstr(env, PPCInstr_Load(2,r_dst,amode, mode64));
1896             return r_dst;
1897          }
1898       }
1899 
1900       switch (op_unop) {
1901       case Iop_8Uto16:
1902       case Iop_8Uto32:
1903       case Iop_8Uto64:
1904       case Iop_16Uto32:
1905       case Iop_16Uto64: {
1906          HReg   r_dst = newVRegI(env);
1907          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1908          UShort mask  = toUShort(op_unop==Iop_16Uto64 ? 0xFFFF :
1909                                  op_unop==Iop_16Uto32 ? 0xFFFF : 0xFF);
1910          addInstr(env, PPCInstr_Alu(Palu_AND,r_dst,r_src,
1911                                     PPCRH_Imm(False,mask)));
1912          return r_dst;
1913       }
1914       case Iop_32Uto64: {
1915          HReg r_dst = newVRegI(env);
1916          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1917          vassert(mode64);
1918          addInstr(env,
1919                   PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1920                                 r_dst, r_src, PPCRH_Imm(False,32)));
1921          addInstr(env,
1922                   PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1923                                 r_dst, r_dst, PPCRH_Imm(False,32)));
1924          return r_dst;
1925       }
1926       case Iop_8Sto16:
1927       case Iop_8Sto32:
1928       case Iop_16Sto32: {
1929          HReg   r_dst = newVRegI(env);
1930          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1931          UShort amt   = toUShort(op_unop==Iop_16Sto32 ? 16 : 24);
1932          addInstr(env,
1933                   PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1934                                 r_dst, r_src, PPCRH_Imm(False,amt)));
1935          addInstr(env,
1936                   PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1937                                 r_dst, r_dst, PPCRH_Imm(False,amt)));
1938          return r_dst;
1939       }
1940       case Iop_8Sto64:
1941       case Iop_16Sto64: {
1942          HReg   r_dst = newVRegI(env);
1943          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1944          UShort amt   = toUShort(op_unop==Iop_8Sto64  ? 56 : 48);
1945          vassert(mode64);
1946          addInstr(env,
1947                   PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1948                                 r_dst, r_src, PPCRH_Imm(False,amt)));
1949          addInstr(env,
1950                   PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
1951                                 r_dst, r_dst, PPCRH_Imm(False,amt)));
1952          return r_dst;
1953       }
1954       case Iop_32Sto64: {
1955          HReg   r_dst = newVRegI(env);
1956          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1957 	 vassert(mode64);
1958          /* According to the IBM docs, in 64 bit mode, srawi r,r,0
1959             sign extends the lower 32 bits into the upper 32 bits. */
1960          addInstr(env,
1961                   PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1962                                 r_dst, r_src, PPCRH_Imm(False,0)));
1963          return r_dst;
1964       }
1965       case Iop_Not8:
1966       case Iop_Not16:
1967       case Iop_Not32:
1968       case Iop_Not64: {
1969          if (op_unop == Iop_Not64) vassert(mode64);
1970          HReg r_dst = newVRegI(env);
1971          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1972          addInstr(env, PPCInstr_Unary(Pun_NOT,r_dst,r_src));
1973          return r_dst;
1974       }
1975       case Iop_64HIto32: {
1976          if (!mode64) {
1977             HReg rHi, rLo;
1978             iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg, IEndianess);
1979             return rHi; /* and abandon rLo .. poor wee thing :-) */
1980          } else {
1981             HReg   r_dst = newVRegI(env);
1982             HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1983             addInstr(env,
1984                      PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1985                                    r_dst, r_src, PPCRH_Imm(False,32)));
1986             return r_dst;
1987          }
1988       }
1989       case Iop_64to32: {
1990          if (!mode64) {
1991             HReg rHi, rLo;
1992             iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg, IEndianess);
1993             return rLo; /* similar stupid comment to the above ... */
1994          } else {
1995             /* This is a no-op. */
1996             return iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1997          }
1998       }
1999       case Iop_64to16: {
2000          if (mode64) { /* This is a no-op. */
2001             return iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2002          }
2003          break; /* evidently not used in 32-bit mode */
2004       }
2005       case Iop_16HIto8:
2006       case Iop_32HIto16: {
2007          HReg   r_dst = newVRegI(env);
2008          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2009          UShort shift = toUShort(op_unop == Iop_16HIto8 ? 8 : 16);
2010          addInstr(env,
2011                   PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
2012                                 r_dst, r_src, PPCRH_Imm(False,shift)));
2013          return r_dst;
2014       }
2015       case Iop_128HIto64:
2016          if (mode64) {
2017             HReg rHi, rLo;
2018             iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg, IEndianess);
2019             return rHi; /* and abandon rLo .. poor wee thing :-) */
2020          }
2021          break;
2022       case Iop_128to64:
2023          if (mode64) {
2024             HReg rHi, rLo;
2025             iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg, IEndianess);
2026             return rLo; /* similar stupid comment to the above ... */
2027          }
2028          break;
2029       case Iop_1Uto64:
2030       case Iop_1Uto32:
2031       case Iop_1Uto8:
2032          if ((op_unop != Iop_1Uto64) || mode64) {
2033             HReg        r_dst = newVRegI(env);
2034             PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
2035             addInstr(env, PPCInstr_Set(cond,r_dst));
2036             return r_dst;
2037          }
2038          break;
2039       case Iop_1Sto8:
2040       case Iop_1Sto16:
2041       case Iop_1Sto32: {
2042          /* could do better than this, but for now ... */
2043          HReg        r_dst = newVRegI(env);
2044          PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
2045          addInstr(env, PPCInstr_Set(cond,r_dst));
2046          addInstr(env,
2047                   PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
2048                                 r_dst, r_dst, PPCRH_Imm(False,31)));
2049          addInstr(env,
2050                   PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
2051                                 r_dst, r_dst, PPCRH_Imm(False,31)));
2052          return r_dst;
2053       }
2054       case Iop_1Sto64:
2055          if (mode64) {
2056             /* could do better than this, but for now ... */
2057             HReg        r_dst = newVRegI(env);
2058             PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
2059             addInstr(env, PPCInstr_Set(cond,r_dst));
2060             addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
2061                                         r_dst, r_dst, PPCRH_Imm(False,63)));
2062             addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
2063                                         r_dst, r_dst, PPCRH_Imm(False,63)));
2064             return r_dst;
2065          }
2066          break;
2067 
2068       case Iop_Clz32: case Iop_ClzNat32:
2069       case Iop_Clz64: case Iop_ClzNat64: {
2070          // cntlz is available even in the most basic (earliest) ppc
2071          // variants, so it's safe to generate it unconditionally.
2072          HReg r_src, r_dst;
2073          PPCUnaryOp op_clz = (op_unop == Iop_Clz32 || op_unop == Iop_ClzNat32)
2074                                 ? Pun_CLZ32 : Pun_CLZ64;
2075          if ((op_unop == Iop_Clz64 || op_unop == Iop_ClzNat64) && !mode64)
2076             goto irreducible;
2077          /* Count leading zeroes. */
2078          r_dst = newVRegI(env);
2079          r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2080          addInstr(env, PPCInstr_Unary(op_clz,r_dst,r_src));
2081          return r_dst;
2082       }
2083 
2084       //case Iop_Ctz32:
2085       case Iop_CtzNat32:
2086       //case Iop_Ctz64:
2087       case Iop_CtzNat64:
2088       {
2089          // Generate code using Clz, because we can't assume the host has
2090          // Ctz.  In particular, part of the fix for bug 386945 involves
2091          // creating a Ctz in ir_opt.c from smaller fragments.
2092          PPCUnaryOp op_clz = Pun_CLZ64;
2093          Int WS = 64;
2094          if (op_unop == Iop_Ctz32 || op_unop == Iop_CtzNat32) {
2095             op_clz = Pun_CLZ32;
2096             WS = 32;
2097          }
2098          /* Compute ctz(arg) = wordsize - clz(~arg & (arg - 1)), thusly:
2099             t1 = arg - 1
2100             t2 = not arg
2101             t2 = t2 & t1
2102             t2 = clz t2
2103             t1 = WS
2104             t2 = t1 - t2
2105             // result in t2
2106          */
2107          HReg arg = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2108          HReg t1 = newVRegI(env);
2109          HReg t2 = newVRegI(env);
2110          addInstr(env, PPCInstr_Alu(Palu_SUB, t1, arg, PPCRH_Imm(True, 1)));
2111          addInstr(env, PPCInstr_Unary(Pun_NOT, t2, arg));
2112          addInstr(env, PPCInstr_Alu(Palu_AND, t2, t2, PPCRH_Reg(t1)));
2113          addInstr(env, PPCInstr_Unary(op_clz, t2, t2));
2114          addInstr(env, PPCInstr_LI(t1, WS, False/*!64-bit imm*/));
2115          addInstr(env, PPCInstr_Alu(Palu_SUB, t2, t1, PPCRH_Reg(t2)));
2116          return t2;
2117       }
2118 
2119       case Iop_PopCount64: {
2120          // popcnt{x,d} is only available in later arch revs (ISA 3.0,
2121          // maybe) so it's not really correct to emit it here without a caps
2122          // check for the host.
2123          if (mode64) {
2124             HReg r_dst = newVRegI(env);
2125             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2126             addInstr(env, PPCInstr_Unary(Pun_POP64, r_dst, r_src));
2127             return r_dst;
2128          }
2129          // We don't expect to be required to handle this in 32-bit mode.
2130          break;
2131       }
2132 
2133       case Iop_PopCount32: {
2134          // Similar comment as for Ctz just above applies -- we really
2135          // should have a caps check here.
2136 
2137         HReg r_dst = newVRegI(env);
2138         // This actually generates popcntw, which in 64 bit mode does a
2139         // 32-bit count individually for both low and high halves of the
2140         // word.  Per the comment at the top of iselIntExpr_R, in the 64
2141         // bit mode case, the user of this result is required to ignore
2142         // the upper 32 bits of the result.  In 32 bit mode this is all
2143         // moot.  It is however unclear from the PowerISA 3.0 docs that
2144         // the instruction exists in 32 bit mode; however our own front
2145         // end (guest_ppc_toIR.c) accepts it, so I guess it does exist.
2146         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2147         addInstr(env, PPCInstr_Unary(Pun_POP32, r_dst, r_src));
2148         return r_dst;
2149       }
2150 
2151       case Iop_Reverse8sIn32_x1: {
2152          // A bit of a mouthful, but simply .. 32-bit byte swap.
2153          // This is pretty rubbish code.  We could do vastly better if
2154          // rotates, and better, rotate-inserts, were allowed.  Note that
2155          // even on a 64 bit target, the right shifts must be done as 32-bit
2156          // so as to introduce zero bits in the right places.  So it seems
2157          // simplest to do the whole sequence in 32-bit insns.
2158          /*
2159             r     = <argument>  // working temporary, initial byte order ABCD
2160             Mask  = 00FF00FF
2161             nMask = not Mask
2162             tHi   = and r, Mask
2163             tHi   = shl tHi, 8
2164             tLo   = and r, nMask
2165             tLo   = shr tLo, 8
2166             r     = or tHi, tLo  // now r has order BADC
2167             and repeat for 16 bit chunks ..
2168             Mask  = 0000FFFF
2169             nMask = not Mask
2170             tHi   = and r, Mask
2171             tHi   = shl tHi, 16
2172             tLo   = and r, nMask
2173             tLo   = shr tLo, 16
2174             r     = or tHi, tLo  // now r has order DCBA
2175          */
2176          HReg r_src  = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2177          HReg rr     = newVRegI(env);
2178          HReg rMask  = newVRegI(env);
2179          HReg rnMask = newVRegI(env);
2180          HReg rtHi   = newVRegI(env);
2181          HReg rtLo   = newVRegI(env);
2182          // Copy r_src since we need to modify it
2183          addInstr(env, mk_iMOVds_RR(rr, r_src));
2184          // Swap within 16-bit lanes
2185          addInstr(env, PPCInstr_LI(rMask, 0x00FF00FFULL,
2186                                    False/* !64bit imm*/));
2187          addInstr(env, PPCInstr_Unary(Pun_NOT, rnMask, rMask));
2188          addInstr(env, PPCInstr_Alu(Palu_AND, rtHi, rr, PPCRH_Reg(rMask)));
2189          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32 bit shift*/,
2190                                      rtHi, rtHi,
2191                                      PPCRH_Imm(False/*!signed imm*/, 8)));
2192          addInstr(env, PPCInstr_Alu(Palu_AND, rtLo, rr, PPCRH_Reg(rnMask)));
2193          addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32 bit shift*/,
2194                                      rtLo, rtLo,
2195                                      PPCRH_Imm(False/*!signed imm*/, 8)));
2196          addInstr(env, PPCInstr_Alu(Palu_OR, rr, rtHi, PPCRH_Reg(rtLo)));
2197          // And now swap the two 16-bit chunks
2198          addInstr(env, PPCInstr_LI(rMask, 0x0000FFFFULL,
2199                                    False/* !64bit imm*/));
2200          addInstr(env, PPCInstr_Unary(Pun_NOT, rnMask, rMask));
2201          addInstr(env, PPCInstr_Alu(Palu_AND, rtHi, rr, PPCRH_Reg(rMask)));
2202          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32 bit shift*/,
2203                                      rtHi, rtHi,
2204                                      PPCRH_Imm(False/*!signed imm*/, 16)));
2205          addInstr(env, PPCInstr_Alu(Palu_AND, rtLo, rr, PPCRH_Reg(rnMask)));
2206          addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32 bit shift*/,
2207                                      rtLo, rtLo,
2208                                      PPCRH_Imm(False/*!signed imm*/, 16)));
2209          addInstr(env, PPCInstr_Alu(Palu_OR, rr, rtHi, PPCRH_Reg(rtLo)));
2210          return rr;
2211       }
2212 
2213       case Iop_Reverse8sIn64_x1: {
2214 	 /* See Iop_Reverse8sIn32_x1, but extended to 64bit.
2215             Can only be used in 64bit mode.  */
2216          vassert (mode64);
2217 
2218          HReg r_src  = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2219          HReg rr     = newVRegI(env);
2220          HReg rMask  = newVRegI(env);
2221          HReg rnMask = newVRegI(env);
2222          HReg rtHi   = newVRegI(env);
2223          HReg rtLo   = newVRegI(env);
2224 
2225          // Copy r_src since we need to modify it
2226          addInstr(env, mk_iMOVds_RR(rr, r_src));
2227 
2228          // r = (r & 0x00FF00FF00FF00FF) << 8 | (r & 0xFF00FF00FF00FF00) >> 8
2229          addInstr(env, PPCInstr_LI(rMask, 0x00FF00FF00FF00FFULL,
2230                                    True/* 64bit imm*/));
2231          addInstr(env, PPCInstr_Unary(Pun_NOT, rnMask, rMask));
2232          addInstr(env, PPCInstr_Alu(Palu_AND, rtHi, rr, PPCRH_Reg(rMask)));
2233          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64 bit shift*/,
2234                                      rtHi, rtHi,
2235                                      PPCRH_Imm(False/*!signed imm*/, 8)));
2236          addInstr(env, PPCInstr_Alu(Palu_AND, rtLo, rr, PPCRH_Reg(rnMask)));
2237          addInstr(env, PPCInstr_Shft(Pshft_SHR, False/*64 bit shift*/,
2238                                      rtLo, rtLo,
2239                                      PPCRH_Imm(False/*!signed imm*/, 8)));
2240          addInstr(env, PPCInstr_Alu(Palu_OR, rr, rtHi, PPCRH_Reg(rtLo)));
2241 
2242          // r = (r & 0x0000FFFF0000FFFF) << 16 | (r & 0xFFFF0000FFFF0000) >> 16
2243          addInstr(env, PPCInstr_LI(rMask, 0x0000FFFF0000FFFFULL,
2244                                    True/* !64bit imm*/));
2245          addInstr(env, PPCInstr_Unary(Pun_NOT, rnMask, rMask));
2246          addInstr(env, PPCInstr_Alu(Palu_AND, rtHi, rr, PPCRH_Reg(rMask)));
2247          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64 bit shift*/,
2248                                      rtHi, rtHi,
2249                                      PPCRH_Imm(False/*!signed imm*/, 16)));
2250          addInstr(env, PPCInstr_Alu(Palu_AND, rtLo, rr, PPCRH_Reg(rnMask)));
2251          addInstr(env, PPCInstr_Shft(Pshft_SHR, False/*64 bit shift*/,
2252                                      rtLo, rtLo,
2253                                      PPCRH_Imm(False/*!signed imm*/, 16)));
2254          addInstr(env, PPCInstr_Alu(Palu_OR, rr, rtHi, PPCRH_Reg(rtLo)));
2255 
2256          // r = (r & 0x00000000FFFFFFFF) << 32 | (r & 0xFFFFFFFF00000000) >> 32
2257          /* We don't need to mask anymore, just two more shifts and an or.  */
2258          addInstr(env, mk_iMOVds_RR(rtLo, rr));
2259          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64 bit shift*/,
2260                                      rtLo, rtLo,
2261                                      PPCRH_Imm(False/*!signed imm*/, 32)));
2262          addInstr(env, PPCInstr_Shft(Pshft_SHR, False/*64 bit shift*/,
2263                                      rr, rr,
2264                                      PPCRH_Imm(False/*!signed imm*/, 32)));
2265          addInstr(env, PPCInstr_Alu(Palu_OR, rr, rr, PPCRH_Reg(rtLo)));
2266 
2267          return rr;
2268       }
2269 
2270       case Iop_Left8:
2271       case Iop_Left16:
2272       case Iop_Left32:
2273       case Iop_Left64: {
2274          HReg r_src, r_dst;
2275          if (op_unop == Iop_Left64 && !mode64)
2276             goto irreducible;
2277          r_dst = newVRegI(env);
2278          r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2279          addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
2280          addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
2281          return r_dst;
2282       }
2283 
2284       case Iop_CmpwNEZ32: {
2285          HReg r_dst = newVRegI(env);
2286          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2287          addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
2288          addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
2289          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
2290                                      r_dst, r_dst, PPCRH_Imm(False, 31)));
2291          return r_dst;
2292       }
2293 
2294       case Iop_CmpwNEZ64: {
2295          HReg r_dst = newVRegI(env);
2296          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2297          if (!mode64) goto irreducible;
2298          addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
2299          addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
2300          addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
2301                                      r_dst, r_dst, PPCRH_Imm(False, 63)));
2302          return r_dst;
2303       }
2304 
2305       case Iop_V128to32: {
2306          HReg        r_aligned16;
2307          HReg        dst  = newVRegI(env);
2308          HReg        vec  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
2309          PPCAMode *am_off0, *am_off_word0;
2310          sub_from_sp( env, 32 );     // Move SP down 32 bytes
2311 
2312          // get a quadword aligned address within our stack space
2313          r_aligned16 = get_sp_aligned16( env );
2314          am_off0  = PPCAMode_IR( 0, r_aligned16 );
2315 
2316          /* Note that the store below (done via PPCInstr_AvLdSt) uses
2317           * stvx, which stores the vector in proper LE format,
2318           * with byte zero (far right byte of the register in LE format)
2319           * stored at the lowest memory address.  Therefore, to obtain
2320           * integer word zero, we need to use that lowest memory address
2321           * as the base for the load.
2322           */
2323          if (IEndianess == Iend_LE)
2324             am_off_word0 = am_off0;
2325          else
2326             am_off_word0 = PPCAMode_IR( 12,r_aligned16 );
2327 
2328          // store vec, load low word to dst
2329          addInstr(env,
2330                   PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
2331          addInstr(env,
2332                   PPCInstr_Load( 4, dst, am_off_word0, mode64 ));
2333 
2334          add_to_sp( env, 32 );       // Reset SP
2335          return dst;
2336       }
2337 
2338       case Iop_V128to64:
2339       case Iop_V128HIto64:
2340          if (mode64) {
2341             HReg     r_aligned16;
2342             HReg     dst = newVRegI(env);
2343             HReg     vec = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
2344             PPCAMode *am_off0, *am_off8, *am_off_arg;
2345             sub_from_sp( env, 32 );     // Move SP down 32 bytes
2346 
2347             // get a quadword aligned address within our stack space
2348             r_aligned16 = get_sp_aligned16( env );
2349             am_off0 = PPCAMode_IR( 0, r_aligned16 );
2350             am_off8 = PPCAMode_IR( 8 ,r_aligned16 );
2351 
2352             // store vec, load low word or high to dst
2353             addInstr(env,
2354                      PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
2355             if (IEndianess == Iend_LE) {
2356                if (op_unop == Iop_V128HIto64)
2357                   am_off_arg = am_off8;
2358                else
2359                   am_off_arg = am_off0;
2360             } else {
2361                if (op_unop == Iop_V128HIto64)
2362                   am_off_arg = am_off0;
2363                else
2364                   am_off_arg = am_off8;
2365             }
2366             addInstr(env,
2367                      PPCInstr_Load(
2368                         8, dst,
2369                         am_off_arg,
2370                         mode64 ));
2371 
2372             add_to_sp( env, 32 );       // Reset SP
2373             return dst;
2374          }
2375          break;
2376       case Iop_16to8:
2377       case Iop_32to8:
2378       case Iop_32to16:
2379       case Iop_64to8:
2380          /* These are no-ops. */
2381          return iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2382 
2383       /* ReinterpF64asI64(e) */
2384       /* Given an IEEE754 double, produce an I64 with the same bit
2385          pattern. */
2386       case Iop_ReinterpF64asI64:
2387          if (mode64) {
2388             PPCAMode *am_addr;
2389             HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
2390             HReg r_dst  = newVRegI(env);
2391 
2392             sub_from_sp( env, 16 );     // Move SP down 16 bytes
2393             am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
2394 
2395             // store as F64
2396             addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
2397                                            fr_src, am_addr ));
2398             // load as Ity_I64
2399             addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
2400 
2401             add_to_sp( env, 16 );       // Reset SP
2402             return r_dst;
2403          }
2404          break;
2405 
2406       /* ReinterpF32asI32(e) */
2407       /* Given an IEEE754 float, produce an I32 with the same bit
2408          pattern. */
2409       case Iop_ReinterpF32asI32: {
2410          /* I believe this generates correct code for both 32- and
2411             64-bit hosts. */
2412          PPCAMode *am_addr;
2413          HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg, IEndianess);
2414          HReg r_dst  = newVRegI(env);
2415 
2416          sub_from_sp( env, 16 );     // Move SP down 16 bytes
2417          am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
2418 
2419          // store as F32
2420          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
2421                                         fr_src, am_addr ));
2422          // load as Ity_I32
2423          addInstr(env, PPCInstr_Load( 4, r_dst, am_addr, mode64 ));
2424 
2425          add_to_sp( env, 16 );       // Reset SP
2426          return r_dst;
2427       }
2428       break;
2429 
2430       case Iop_ReinterpD64asI64:
2431          if (mode64) {
2432             PPCAMode *am_addr;
2433             HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
2434             HReg r_dst  = newVRegI(env);
2435 
2436             sub_from_sp( env, 16 );     // Move SP down 16 bytes
2437             am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
2438 
2439             // store as D64
2440             addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
2441                                            fr_src, am_addr ));
2442             // load as Ity_I64
2443             addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
2444             add_to_sp( env, 16 );       // Reset SP
2445             return r_dst;
2446          }
2447          break;
2448 
2449       case Iop_BCDtoDPB: {
2450          /* the following is only valid in 64 bit mode */
2451          if (!mode64) break;
2452 
2453          PPCCondCode cc;
2454          UInt        argiregs;
2455          HReg        argregs[1];
2456          HReg        r_dst  = newVRegI(env);
2457          Int         argreg;
2458 
2459          argiregs = 0;
2460          argreg = 0;
2461          argregs[0] = hregPPC_GPR3(mode64);
2462 
2463          argiregs |= (1 << (argreg+3));
2464          addInstr(env, mk_iMOVds_RR( argregs[argreg++],
2465                                      iselWordExpr_R(env, e->Iex.Unop.arg,
2466                                                     IEndianess) ) );
2467 
2468          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
2469          if (IEndianess == Iend_LE) {
2470              addInstr(env, PPCInstr_Call( cc, (Addr)h_calc_BCDtoDPB,
2471                                           argiregs,
2472                                           mk_RetLoc_simple(RLPri_Int)) );
2473          } else {
2474              HWord*      fdescr;
2475              fdescr = (HWord*)h_calc_BCDtoDPB;
2476              addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]),
2477                                           argiregs,
2478                                           mk_RetLoc_simple(RLPri_Int)) );
2479          }
2480 
2481          addInstr(env, mk_iMOVds_RR(r_dst, argregs[0]));
2482          return r_dst;
2483       }
2484 
2485       case Iop_DPBtoBCD: {
2486          /* the following is only valid in 64 bit mode */
2487          if (!mode64) break;
2488 
2489          PPCCondCode cc;
2490          UInt        argiregs;
2491          HReg        argregs[1];
2492          HReg        r_dst  = newVRegI(env);
2493          Int         argreg;
2494 
2495          argiregs = 0;
2496          argreg = 0;
2497          argregs[0] = hregPPC_GPR3(mode64);
2498 
2499          argiregs |= (1 << (argreg+3));
2500          addInstr(env, mk_iMOVds_RR( argregs[argreg++],
2501                                      iselWordExpr_R(env, e->Iex.Unop.arg,
2502                                                     IEndianess) ) );
2503 
2504          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
2505 
2506         if (IEndianess == Iend_LE) {
2507             addInstr(env, PPCInstr_Call( cc, (Addr)h_calc_DPBtoBCD,
2508                                          argiregs,
2509                                          mk_RetLoc_simple(RLPri_Int) ) );
2510         } else {
2511             HWord*      fdescr;
2512             fdescr = (HWord*)h_calc_DPBtoBCD;
2513             addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]),
2514                                          argiregs,
2515                                          mk_RetLoc_simple(RLPri_Int) ) );
2516          }
2517 
2518          addInstr(env, mk_iMOVds_RR(r_dst, argregs[0]));
2519          return r_dst;
2520       }
2521       case Iop_F32toF16x4: {
2522          HReg vdst = newVRegV(env);    /* V128 */
2523          HReg dst  = newVRegI(env);    /* I64*/
2524          HReg r0 = newVRegI(env);    /* I16*/
2525          HReg r1 = newVRegI(env);    /* I16*/
2526          HReg r2 = newVRegI(env);    /* I16*/
2527          HReg r3 = newVRegI(env);    /* I16*/
2528          HReg vsrc  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
2529          PPCAMode *am_off0, *am_off2, *am_off4, *am_off6, *am_off8;
2530          PPCAMode *am_off10, *am_off12, *am_off14;
2531          HReg r_aligned16;
2532 
2533          sub_from_sp( env, 32 );     // Move SP down
2534 
2535          /* issue instruction */
2536          addInstr(env, PPCInstr_AvUnary(Pav_F32toF16x4, vdst, vsrc));
2537 
2538          /* Get a  quadword aligned address within our stack space */
2539          r_aligned16 = get_sp_aligned16( env );
2540          am_off0  = PPCAMode_IR( 0, r_aligned16 );
2541          am_off2  = PPCAMode_IR( 2, r_aligned16 );
2542          am_off4  = PPCAMode_IR( 4, r_aligned16 );
2543          am_off6  = PPCAMode_IR( 6, r_aligned16 );
2544          am_off8  = PPCAMode_IR( 8, r_aligned16 );
2545          am_off10 = PPCAMode_IR( 10, r_aligned16 );
2546          am_off12 = PPCAMode_IR( 12, r_aligned16 );
2547          am_off14 = PPCAMode_IR( 14, r_aligned16 );
2548 
2549          /* Store v128 result to stack. */
2550          addInstr(env, PPCInstr_AvLdSt(False/*store*/, 16, vdst, am_off0));
2551 
2552          /* fetch four I16 from V128, store into contiguous I64 via stack,  */
2553          if (IEndianess == Iend_LE) {
2554             addInstr(env, PPCInstr_Load( 2, r3, am_off12, mode64));
2555             addInstr(env, PPCInstr_Load( 2, r2, am_off8, mode64));
2556             addInstr(env, PPCInstr_Load( 2, r1, am_off4, mode64));
2557             addInstr(env, PPCInstr_Load( 2, r0, am_off0, mode64));
2558          } else {
2559             addInstr(env, PPCInstr_Load( 2, r0, am_off14, mode64));
2560             addInstr(env, PPCInstr_Load( 2, r1, am_off10, mode64));
2561             addInstr(env, PPCInstr_Load( 2, r2, am_off6, mode64));
2562             addInstr(env, PPCInstr_Load( 2, r3, am_off2, mode64));
2563          }
2564 
2565          /* store in contiguous 64-bit values */
2566          addInstr(env, PPCInstr_Store( 2, am_off6, r3, mode64));
2567          addInstr(env, PPCInstr_Store( 2, am_off4, r2, mode64));
2568          addInstr(env, PPCInstr_Store( 2, am_off2, r1, mode64));
2569          addInstr(env, PPCInstr_Store( 2, am_off0, r0, mode64));
2570 
2571          /* Fetch I64 */
2572          addInstr(env, PPCInstr_Load(8, dst, am_off0, mode64));
2573 
2574          add_to_sp( env, 32 );          // Reset SP
2575          return dst;
2576       }
2577 
2578       default:
2579          break;
2580       }
2581 
2582      switch (e->Iex.Unop.op) {
2583         case Iop_ExtractExpD64: {
2584 
2585             HReg fr_dst = newVRegI(env);
2586             HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
2587             HReg tmp    = newVRegF(env);
2588             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
2589             addInstr(env, PPCInstr_Dfp64Unary(Pfp_DXEX, tmp, fr_src));
2590 
2591             // put the D64 result into a integer register
2592             sub_from_sp( env, 16 );
2593             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
2594             addInstr(env, PPCInstr_Load(8, fr_dst, zero_r1, env->mode64));
2595             add_to_sp( env, 16 );
2596             return fr_dst;
2597          }
2598          case Iop_ExtractExpD128: {
2599             HReg fr_dst = newVRegI(env);
2600             HReg r_srcHi;
2601             HReg r_srcLo;
2602             HReg tmp    = newVRegF(env);
2603             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
2604 
2605             iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Unop.arg,
2606                            IEndianess);
2607             addInstr(env, PPCInstr_ExtractExpD128(Pfp_DXEXQ, tmp,
2608                                                   r_srcHi, r_srcLo));
2609 
2610             sub_from_sp( env, 16 );
2611             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
2612             addInstr(env, PPCInstr_Load(8, fr_dst, zero_r1, env->mode64));
2613             add_to_sp( env, 16 );
2614             return fr_dst;
2615          }
2616          default:
2617             break;
2618       }
2619 
2620       break;
2621    }
2622 
2623    /* --------- GET --------- */
2624    case Iex_Get: {
2625       if (ty == Ity_I8  || ty == Ity_I16 ||
2626           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
2627          HReg r_dst = newVRegI(env);
2628          PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
2629                                           GuestStatePtr(mode64) );
2630          addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
2631                                       r_dst, am_addr, mode64 ));
2632          return r_dst;
2633       }
2634       break;
2635    }
2636 
2637    case Iex_GetI: {
2638       PPCAMode* src_am
2639          = genGuestArrayOffset( env, e->Iex.GetI.descr,
2640                                 e->Iex.GetI.ix, e->Iex.GetI.bias,
2641                                 IEndianess );
2642       HReg r_dst = newVRegI(env);
2643       if (mode64 && ty == Ity_I64) {
2644          addInstr(env, PPCInstr_Load( toUChar(8),
2645                                       r_dst, src_am, mode64 ));
2646          return r_dst;
2647       }
2648       if ((!mode64) && ty == Ity_I32) {
2649          addInstr(env, PPCInstr_Load( toUChar(4),
2650                                       r_dst, src_am, mode64 ));
2651          return r_dst;
2652       }
2653       break;
2654    }
2655 
2656    /* --------- CCALL --------- */
2657    case Iex_CCall: {
2658       vassert(ty == e->Iex.CCall.retty); /* well-formedness of IR */
2659 
2660       /* be very restrictive for now.  Only 32/64-bit ints allowed for
2661          args, and 32 bits or host machine word for return type. */
2662       if (!(ty == Ity_I32 || (mode64 && ty == Ity_I64)))
2663          goto irreducible;
2664 
2665       /* Marshal args, do the call, clear stack. */
2666       UInt   addToSp = 0;
2667       RetLoc rloc    = mk_RetLoc_INVALID();
2668       doHelperCall( &addToSp, &rloc, env, NULL/*guard*/,
2669                     e->Iex.CCall.cee, e->Iex.CCall.retty, e->Iex.CCall.args,
2670                     IEndianess );
2671       vassert(is_sane_RetLoc(rloc));
2672       vassert(rloc.pri == RLPri_Int);
2673       vassert(addToSp == 0);
2674 
2675       /* GPR3 now holds the destination address from Pin_Goto */
2676       HReg r_dst = newVRegI(env);
2677       addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
2678       return r_dst;
2679    }
2680 
2681    /* --------- LITERAL --------- */
2682    /* 32/16/8-bit literals */
2683    case Iex_Const: {
2684       Long l;
2685       HReg r_dst = newVRegI(env);
2686       IRConst* con = e->Iex.Const.con;
2687       switch (con->tag) {
2688          case Ico_U64: if (!mode64) goto irreducible;
2689                        l = (Long)            con->Ico.U64; break;
2690          case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
2691          case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
2692          case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
2693          default:      vpanic("iselIntExpr_R.const(ppc)");
2694       }
2695       addInstr(env, PPCInstr_LI(r_dst, (ULong)l, mode64));
2696       return r_dst;
2697    }
2698 
2699    /* --------- MULTIPLEX --------- */
2700    case Iex_ITE: { // VFD
2701       if ((ty == Ity_I8  || ty == Ity_I16 ||
2702            ty == Ity_I32 || ((ty == Ity_I64) && mode64)) &&
2703           typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) {
2704          PPCRI* r1    = iselWordExpr_RI(env, e->Iex.ITE.iftrue, IEndianess);
2705          HReg   r0    = iselWordExpr_R(env, e->Iex.ITE.iffalse, IEndianess);
2706          HReg   r_dst = newVRegI(env);
2707          addInstr(env, mk_iMOVds_RR(r_dst,r0));
2708          PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond, IEndianess);
2709          addInstr(env, PPCInstr_CMov(cc, r_dst, r1));
2710          return r_dst;
2711       }
2712       break;
2713    }
2714 
2715    default:
2716       break;
2717    } /* switch (e->tag) */
2718 
2719 
2720    /* We get here if no pattern matched. */
2721  irreducible:
2722    ppIRExpr(e);
2723    vpanic("iselIntExpr_R(ppc): cannot reduce tree");
2724 }
2725 
2726 
2727 /*---------------------------------------------------------*/
2728 /*--- ISEL: Integer expression auxiliaries              ---*/
2729 /*---------------------------------------------------------*/
2730 
2731 /* --------------------- AMODEs --------------------- */
2732 
2733 /* Return an AMode which computes the value of the specified
2734    expression, possibly also adding insns to the code list as a
2735    result.  The expression may only be a word-size one.
2736 */
2737 
uInt_fits_in_16_bits(UInt u)2738 static Bool uInt_fits_in_16_bits ( UInt u )
2739 {
2740    /* Is u the same as the sign-extend of its lower 16 bits? */
2741    UInt v = u & 0xFFFF;
2742 
2743    v = (Int)(v << 16) >> 16;   /* sign extend */
2744 
2745    return u == v;
2746 }
2747 
uLong_fits_in_16_bits(ULong u)2748 static Bool uLong_fits_in_16_bits ( ULong u )
2749 {
2750    /* Is u the same as the sign-extend of its lower 16 bits? */
2751    ULong v = u & 0xFFFFULL;
2752 
2753    v = (Long)(v << 48) >> 48;   /* sign extend */
2754 
2755    return u == v;
2756 }
2757 
uLong_is_4_aligned(ULong u)2758 static Bool uLong_is_4_aligned ( ULong u )
2759 {
2760    return toBool((u & 3ULL) == 0);
2761 }
2762 
sane_AMode(ISelEnv * env,PPCAMode * am)2763 static Bool sane_AMode ( ISelEnv* env, PPCAMode* am )
2764 {
2765    Bool mode64 = env->mode64;
2766    switch (am->tag) {
2767    case Pam_IR:
2768       /* Using uInt_fits_in_16_bits in 64-bit mode seems a bit bogus,
2769          somehow, but I think it's OK. */
2770       return toBool( hregClass(am->Pam.IR.base) == HRcGPR(mode64) &&
2771                      hregIsVirtual(am->Pam.IR.base) &&
2772                      uInt_fits_in_16_bits(am->Pam.IR.index) );
2773    case Pam_RR:
2774       return toBool( hregClass(am->Pam.RR.base) == HRcGPR(mode64) &&
2775                      hregIsVirtual(am->Pam.RR.base) &&
2776                      hregClass(am->Pam.RR.index) == HRcGPR(mode64) &&
2777                      hregIsVirtual(am->Pam.RR.index) );
2778    default:
2779       vpanic("sane_AMode: unknown ppc amode tag");
2780    }
2781 }
2782 
2783 static
iselWordExpr_AMode(ISelEnv * env,const IRExpr * e,IRType xferTy,IREndness IEndianess)2784 PPCAMode* iselWordExpr_AMode ( ISelEnv* env, const IRExpr* e, IRType xferTy,
2785                                IREndness IEndianess )
2786 {
2787    PPCAMode* am = iselWordExpr_AMode_wrk(env, e, xferTy, IEndianess);
2788    vassert(sane_AMode(env, am));
2789    return am;
2790 }
2791 
2792 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_AMode_wrk(ISelEnv * env,const IRExpr * e,IRType xferTy,IREndness IEndianess)2793 static PPCAMode* iselWordExpr_AMode_wrk ( ISelEnv* env, const IRExpr* e,
2794                                           IRType xferTy, IREndness IEndianess )
2795 {
2796    IRType ty = typeOfIRExpr(env->type_env,e);
2797 
2798    if (env->mode64) {
2799 
2800       /* If the data load/store type is I32 or I64, this amode might
2801          be destined for use in ld/ldu/lwa/st/stu.  In which case
2802          insist that if it comes out as an _IR, the immediate must
2803          have its bottom two bits be zero.  This does assume that for
2804          any other type (I8/I16/I128/F32/F64/V128) the amode will not
2805          be parked in any such instruction.  But that seems a
2806          reasonable assumption.  */
2807       Bool aligned4imm = toBool(xferTy == Ity_I32 || xferTy == Ity_I64);
2808 
2809       vassert(ty == Ity_I64);
2810 
2811       /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
2812       if (e->tag == Iex_Binop
2813           && e->Iex.Binop.op == Iop_Add64
2814           && e->Iex.Binop.arg2->tag == Iex_Const
2815           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
2816           && (aligned4imm  ? uLong_is_4_aligned(e->Iex.Binop.arg2
2817                                                  ->Iex.Const.con->Ico.U64)
2818                            : True)
2819           && uLong_fits_in_16_bits(e->Iex.Binop.arg2
2820                                     ->Iex.Const.con->Ico.U64)) {
2821          return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
2822                              iselWordExpr_R(env, e->Iex.Binop.arg1,
2823                                             IEndianess) );
2824       }
2825 
2826       /* Add64(expr,expr) */
2827       if (e->tag == Iex_Binop
2828           && e->Iex.Binop.op == Iop_Add64) {
2829          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
2830          HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
2831          return PPCAMode_RR( r_idx, r_base );
2832       }
2833 
2834    } else {
2835 
2836       vassert(ty == Ity_I32);
2837 
2838       /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
2839       if (e->tag == Iex_Binop
2840           && e->Iex.Binop.op == Iop_Add32
2841           && e->Iex.Binop.arg2->tag == Iex_Const
2842           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
2843           && uInt_fits_in_16_bits(e->Iex.Binop.arg2
2844                                    ->Iex.Const.con->Ico.U32)) {
2845          return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
2846                              iselWordExpr_R(env, e->Iex.Binop.arg1,
2847                                             IEndianess) );
2848       }
2849 
2850       /* Add32(expr,expr) */
2851       if (e->tag == Iex_Binop
2852           && e->Iex.Binop.op == Iop_Add32) {
2853          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
2854          HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
2855          return PPCAMode_RR( r_idx, r_base );
2856       }
2857 
2858    }
2859 
2860    /* Doesn't match anything in particular.  Generate it into
2861       a register and use that. */
2862    return PPCAMode_IR( 0, iselWordExpr_R(env,e,IEndianess) );
2863 }
2864 
2865 
2866 /* --------------------- RH --------------------- */
2867 
2868 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
2869    (reg-or-halfword-immediate).  It's important to specify whether the
2870    immediate is to be regarded as signed or not.  If yes, this will
2871    never return -32768 as an immediate; this guaranteed that all
2872    signed immediates that are return can have their sign inverted if
2873    need be. */
2874 
iselWordExpr_RH(ISelEnv * env,Bool syned,const IRExpr * e,IREndness IEndianess)2875 static PPCRH* iselWordExpr_RH ( ISelEnv* env, Bool syned, const IRExpr* e,
2876                                 IREndness IEndianess )
2877 {
2878   PPCRH* ri = iselWordExpr_RH_wrk(env, syned, e, IEndianess);
2879    /* sanity checks ... */
2880    switch (ri->tag) {
2881    case Prh_Imm:
2882       vassert(ri->Prh.Imm.syned == syned);
2883       if (syned)
2884          vassert(ri->Prh.Imm.imm16 != 0x8000);
2885       return ri;
2886    case Prh_Reg:
2887       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2888       vassert(hregIsVirtual(ri->Prh.Reg.reg));
2889       return ri;
2890    default:
2891       vpanic("iselIntExpr_RH: unknown ppc RH tag");
2892    }
2893 }
2894 
2895 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH_wrk(ISelEnv * env,Bool syned,const IRExpr * e,IREndness IEndianess)2896 static PPCRH* iselWordExpr_RH_wrk ( ISelEnv* env, Bool syned, const IRExpr* e,
2897                                     IREndness IEndianess )
2898 {
2899    ULong u;
2900    Long  l;
2901    IRType ty = typeOfIRExpr(env->type_env,e);
2902    vassert(ty == Ity_I8  || ty == Ity_I16 ||
2903            ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2904 
2905    /* special case: immediate */
2906    if (e->tag == Iex_Const) {
2907       IRConst* con = e->Iex.Const.con;
2908       /* What value are we aiming to generate? */
2909       switch (con->tag) {
2910       /* Note: Not sign-extending - we carry 'syned' around */
2911       case Ico_U64: vassert(env->mode64);
2912                     u =              con->Ico.U64; break;
2913       case Ico_U32: u = 0xFFFFFFFF & con->Ico.U32; break;
2914       case Ico_U16: u = 0x0000FFFF & con->Ico.U16; break;
2915       case Ico_U8:  u = 0x000000FF & con->Ico.U8; break;
2916       default:      vpanic("iselIntExpr_RH.Iex_Const(ppch)");
2917       }
2918       l = (Long)u;
2919       /* Now figure out if it's representable. */
2920       if (!syned && u <= 65535) {
2921          return PPCRH_Imm(False/*unsigned*/, toUShort(u & 0xFFFF));
2922       }
2923       if (syned && l >= -32767 && l <= 32767) {
2924          return PPCRH_Imm(True/*signed*/, toUShort(u & 0xFFFF));
2925       }
2926       /* no luck; use the Slow Way. */
2927    }
2928 
2929    /* default case: calculate into a register and return that */
2930    return PPCRH_Reg( iselWordExpr_R ( env, e, IEndianess ) );
2931 }
2932 
2933 
2934 /* --------------------- RIs --------------------- */
2935 
2936 /* Calculate an expression into an PPCRI operand.  As with
2937    iselIntExpr_R, the expression can have type 32, 16 or 8 bits, or,
2938    in 64-bit mode, 64 bits. */
2939 
iselWordExpr_RI(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2940 static PPCRI* iselWordExpr_RI ( ISelEnv* env, const IRExpr* e,
2941                                 IREndness IEndianess )
2942 {
2943    PPCRI* ri = iselWordExpr_RI_wrk(env, e, IEndianess);
2944    /* sanity checks ... */
2945    switch (ri->tag) {
2946    case Pri_Imm:
2947       return ri;
2948    case Pri_Reg:
2949       vassert(hregClass(ri->Pri.Reg) == HRcGPR(env->mode64));
2950       vassert(hregIsVirtual(ri->Pri.Reg));
2951       return ri;
2952    default:
2953       vpanic("iselIntExpr_RI: unknown ppc RI tag");
2954    }
2955 }
2956 
2957 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RI_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2958 static PPCRI* iselWordExpr_RI_wrk ( ISelEnv* env, const IRExpr* e,
2959                                     IREndness IEndianess )
2960 {
2961    Long  l;
2962    IRType ty = typeOfIRExpr(env->type_env,e);
2963    vassert(ty == Ity_I8  || ty == Ity_I16 ||
2964            ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2965 
2966    /* special case: immediate */
2967    if (e->tag == Iex_Const) {
2968       IRConst* con = e->Iex.Const.con;
2969       switch (con->tag) {
2970       case Ico_U64: vassert(env->mode64);
2971                     l = (Long)            con->Ico.U64; break;
2972       case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
2973       case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
2974       case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
2975       default:      vpanic("iselIntExpr_RI.Iex_Const(ppch)");
2976       }
2977       return PPCRI_Imm((ULong)l);
2978    }
2979 
2980    /* default case: calculate into a register and return that */
2981    return PPCRI_Reg( iselWordExpr_R ( env, e, IEndianess ) );
2982 }
2983 
2984 
2985 /* --------------------- RH5u --------------------- */
2986 
2987 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
2988    being an immediate in the range 1 .. 31 inclusive.  Used for doing
2989    shift amounts.  Only used in 32-bit mode. */
2990 
iselWordExpr_RH5u(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2991 static PPCRH* iselWordExpr_RH5u ( ISelEnv* env, const IRExpr* e,
2992                                   IREndness IEndianess )
2993 {
2994    PPCRH* ri;
2995    vassert(!env->mode64);
2996    ri = iselWordExpr_RH5u_wrk(env, e, IEndianess);
2997    /* sanity checks ... */
2998    switch (ri->tag) {
2999    case Prh_Imm:
3000       vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 31);
3001       vassert(!ri->Prh.Imm.syned);
3002       return ri;
3003    case Prh_Reg:
3004       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
3005       vassert(hregIsVirtual(ri->Prh.Reg.reg));
3006       return ri;
3007    default:
3008       vpanic("iselIntExpr_RH5u: unknown ppc RI tag");
3009    }
3010 }
3011 
3012 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH5u_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)3013 static PPCRH* iselWordExpr_RH5u_wrk ( ISelEnv* env, const IRExpr* e,
3014                                       IREndness IEndianess )
3015 {
3016    IRType ty = typeOfIRExpr(env->type_env,e);
3017    vassert(ty == Ity_I8);
3018 
3019    /* special case: immediate */
3020    if (e->tag == Iex_Const
3021        && e->Iex.Const.con->tag == Ico_U8
3022        && e->Iex.Const.con->Ico.U8 >= 1
3023        && e->Iex.Const.con->Ico.U8 <= 31) {
3024       return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
3025    }
3026 
3027    /* default case: calculate into a register and return that */
3028    return PPCRH_Reg( iselWordExpr_R ( env, e, IEndianess ) );
3029 }
3030 
3031 
3032 /* --------------------- RH6u --------------------- */
3033 
3034 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter
3035    being an immediate in the range 1 .. 63 inclusive.  Used for doing
3036    shift amounts.  Only used in 64-bit mode. */
3037 
iselWordExpr_RH6u(ISelEnv * env,const IRExpr * e,IREndness IEndianess)3038 static PPCRH* iselWordExpr_RH6u ( ISelEnv* env, const IRExpr* e,
3039                                   IREndness IEndianess )
3040 {
3041    PPCRH* ri;
3042    vassert(env->mode64);
3043    ri = iselWordExpr_RH6u_wrk(env, e, IEndianess);
3044    /* sanity checks ... */
3045    switch (ri->tag) {
3046    case Prh_Imm:
3047       vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 63);
3048       vassert(!ri->Prh.Imm.syned);
3049       return ri;
3050    case Prh_Reg:
3051       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
3052       vassert(hregIsVirtual(ri->Prh.Reg.reg));
3053       return ri;
3054    default:
3055       vpanic("iselIntExpr_RH6u: unknown ppc64 RI tag");
3056    }
3057 }
3058 
3059 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH6u_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)3060 static PPCRH* iselWordExpr_RH6u_wrk ( ISelEnv* env, const IRExpr* e,
3061                                       IREndness IEndianess )
3062 {
3063    IRType ty = typeOfIRExpr(env->type_env,e);
3064    vassert(ty == Ity_I8);
3065 
3066    /* special case: immediate */
3067    if (e->tag == Iex_Const
3068        && e->Iex.Const.con->tag == Ico_U8
3069        && e->Iex.Const.con->Ico.U8 >= 1
3070        && e->Iex.Const.con->Ico.U8 <= 63) {
3071       return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
3072    }
3073 
3074    /* default case: calculate into a register and return that */
3075    return PPCRH_Reg( iselWordExpr_R ( env, e, IEndianess ) );
3076 }
3077 
3078 
3079 /* --------------------- CONDCODE --------------------- */
3080 
3081 /* Generate code to evaluated a bit-typed expression, returning the
3082    condition code which would correspond when the expression would
3083    notionally have returned 1. */
3084 
iselCondCode(ISelEnv * env,const IRExpr * e,IREndness IEndianess)3085 static PPCCondCode iselCondCode ( ISelEnv* env, const IRExpr* e,
3086                                   IREndness IEndianess )
3087 {
3088    /* Uh, there's nothing we can sanity check here, unfortunately. */
3089    return iselCondCode_wrk(env,e, IEndianess);
3090 }
3091 
3092 /* DO NOT CALL THIS DIRECTLY ! */
iselCondCode_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)3093 static PPCCondCode iselCondCode_wrk ( ISelEnv* env, const IRExpr* e,
3094                                       IREndness IEndianess )
3095 {
3096    vassert(e);
3097    vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
3098 
3099    /* Constant 1:Bit */
3100    if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True) {
3101       // Make a compare that will always be true:
3102       HReg r_zero = newVRegI(env);
3103       addInstr(env, PPCInstr_LI(r_zero, 0, env->mode64));
3104       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3105                                  7/*cr*/, r_zero, PPCRH_Reg(r_zero)));
3106       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
3107    }
3108 
3109    /* Not1(...) */
3110    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
3111       /* Generate code for the arg, and negate the test condition */
3112       PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
3113       cond.test = invertCondTest(cond.test);
3114       return cond;
3115    }
3116 
3117    /* --- patterns rooted at: 32to1 or 64to1 --- */
3118 
3119    /* 32to1, 64to1 */
3120    if (e->tag == Iex_Unop &&
3121        (e->Iex.Unop.op == Iop_32to1 || e->Iex.Unop.op == Iop_64to1)) {
3122       HReg src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
3123       HReg tmp = newVRegI(env);
3124       /* could do better, probably -- andi. */
3125       addInstr(env, PPCInstr_Alu(Palu_AND, tmp,
3126                                  src, PPCRH_Imm(False,1)));
3127       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3128                                  7/*cr*/, tmp, PPCRH_Imm(False,1)));
3129       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
3130    }
3131 
3132    /* --- patterns rooted at: CmpNEZ8 --- */
3133 
3134    /* CmpNEZ8(x) */
3135    /* Note this cloned as CmpNE8(x,0) below. */
3136    /* could do better -- andi. */
3137    if (e->tag == Iex_Unop
3138        && e->Iex.Unop.op == Iop_CmpNEZ8) {
3139       HReg arg = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
3140       HReg tmp = newVRegI(env);
3141       addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
3142                                  PPCRH_Imm(False,0xFF)));
3143       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3144                                  7/*cr*/, tmp, PPCRH_Imm(False,0)));
3145       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3146    }
3147 
3148    /* --- patterns rooted at: CmpNEZ32 --- */
3149 
3150    /* CmpNEZ32(x) */
3151    if (e->tag == Iex_Unop
3152        && e->Iex.Unop.op == Iop_CmpNEZ32) {
3153       HReg r1 = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
3154       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3155                                  7/*cr*/, r1, PPCRH_Imm(False,0)));
3156       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3157    }
3158 
3159    /* --- patterns rooted at: Cmp*32* --- */
3160 
3161    /* Cmp*32*(x,y) */
3162    if (e->tag == Iex_Binop
3163        && (e->Iex.Binop.op == Iop_CmpEQ32
3164            || e->Iex.Binop.op == Iop_CmpNE32
3165            || e->Iex.Binop.op == Iop_CmpLT32S
3166            || e->Iex.Binop.op == Iop_CmpLT32U
3167            || e->Iex.Binop.op == Iop_CmpLE32S
3168            || e->Iex.Binop.op == Iop_CmpLE32U)) {
3169       Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S ||
3170                     e->Iex.Binop.op == Iop_CmpLE32S);
3171       HReg   r1  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3172       PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2, IEndianess);
3173       addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
3174                                  7/*cr*/, r1, ri2));
3175 
3176       switch (e->Iex.Binop.op) {
3177       case Iop_CmpEQ32:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
3178       case Iop_CmpNE32:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3179       case Iop_CmpLT32U: case Iop_CmpLT32S:
3180          return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
3181       case Iop_CmpLE32U: case Iop_CmpLE32S:
3182          return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
3183       default: vpanic("iselCondCode(ppc): CmpXX32");
3184       }
3185    }
3186 
3187    /* --- patterns rooted at: CmpNEZ64 --- */
3188 
3189    /* CmpNEZ64 */
3190    if (e->tag == Iex_Unop
3191        && e->Iex.Unop.op == Iop_CmpNEZ64) {
3192       if (!env->mode64) {
3193          HReg hi, lo;
3194          HReg tmp = newVRegI(env);
3195          iselInt64Expr( &hi, &lo, env, e->Iex.Unop.arg, IEndianess );
3196          addInstr(env, PPCInstr_Alu(Palu_OR, tmp, lo, PPCRH_Reg(hi)));
3197          addInstr(env, PPCInstr_Cmp(False/*sign*/, True/*32bit cmp*/,
3198                                     7/*cr*/, tmp,PPCRH_Imm(False,0)));
3199          return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3200       } else {  // mode64
3201          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
3202          addInstr(env, PPCInstr_Cmp(False/*sign*/, False/*64bit cmp*/,
3203                                     7/*cr*/, r_src,PPCRH_Imm(False,0)));
3204          return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3205       }
3206    }
3207 
3208    /* --- patterns rooted at: Cmp*64* --- */
3209 
3210    /* Cmp*64*(x,y) */
3211    if (e->tag == Iex_Binop
3212        && (e->Iex.Binop.op == Iop_CmpEQ64
3213            || e->Iex.Binop.op == Iop_CmpNE64
3214            || e->Iex.Binop.op == Iop_CmpLT64S
3215            || e->Iex.Binop.op == Iop_CmpLT64U
3216            || e->Iex.Binop.op == Iop_CmpLE64S
3217            || e->Iex.Binop.op == Iop_CmpLE64U)) {
3218       Bool   syned = (e->Iex.Binop.op == Iop_CmpLT64S ||
3219                       e->Iex.Binop.op == Iop_CmpLE64S);
3220       HReg    r1 = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3221       PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2, IEndianess);
3222       vassert(env->mode64);
3223       addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
3224                                  7/*cr*/, r1, ri2));
3225 
3226       switch (e->Iex.Binop.op) {
3227       case Iop_CmpEQ64:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
3228       case Iop_CmpNE64:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3229       case Iop_CmpLT64U: return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
3230       case Iop_CmpLE64U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
3231       default: vpanic("iselCondCode(ppc): CmpXX64");
3232       }
3233    }
3234 
3235    /* --- patterns rooted at: CmpNE8 --- */
3236 
3237    /* CmpNE8(x,0) */
3238    /* Note this is a direct copy of CmpNEZ8 above. */
3239    /* could do better -- andi. */
3240    if (e->tag == Iex_Binop
3241        && e->Iex.Binop.op == Iop_CmpNE8
3242        && isZeroU8(e->Iex.Binop.arg2)) {
3243       HReg arg = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3244       HReg tmp = newVRegI(env);
3245       addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
3246                                  PPCRH_Imm(False,0xFF)));
3247       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3248                                  7/*cr*/, tmp, PPCRH_Imm(False,0)));
3249       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3250    }
3251 
3252    /* var */
3253    if (e->tag == Iex_RdTmp) {
3254       HReg r_src      = lookupIRTemp(env, e->Iex.RdTmp.tmp);
3255       HReg src_masked = newVRegI(env);
3256       addInstr(env,
3257                PPCInstr_Alu(Palu_AND, src_masked,
3258                             r_src, PPCRH_Imm(False,1)));
3259       addInstr(env,
3260                PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3261                             7/*cr*/, src_masked, PPCRH_Imm(False,1)));
3262       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
3263    }
3264 
3265    vex_printf("iselCondCode(ppc): No such tag(%u)\n", e->tag);
3266    ppIRExpr(e);
3267    vpanic("iselCondCode(ppc)");
3268 }
3269 
3270 
3271 /*---------------------------------------------------------*/
3272 /*--- ISEL: Integer expressions (128 bit)               ---*/
3273 /*---------------------------------------------------------*/
3274 
3275 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
3276    which is returned as the first two parameters.  As with
3277    iselWordExpr_R, these may be either real or virtual regs; in any
3278    case they must not be changed by subsequent code emitted by the
3279    caller.  */
3280 
iselInt128Expr(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3281 static void iselInt128Expr ( HReg* rHi, HReg* rLo, ISelEnv* env,
3282                              const IRExpr* e, IREndness IEndianess )
3283 {
3284    vassert(env->mode64);
3285    iselInt128Expr_wrk(rHi, rLo, env, e, IEndianess);
3286 #  if 0
3287    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3288 #  endif
3289    vassert(hregClass(*rHi) == HRcGPR(env->mode64));
3290    vassert(hregIsVirtual(*rHi));
3291    vassert(hregClass(*rLo) == HRcGPR(env->mode64));
3292    vassert(hregIsVirtual(*rLo));
3293 }
3294 
3295 /* DO NOT CALL THIS DIRECTLY ! */
iselInt128Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3296 static void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env,
3297                                  const IRExpr* e, IREndness IEndianess )
3298 {
3299    Bool mode64 = env->mode64;
3300 
3301    vassert(e);
3302    vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
3303 
3304    /* read 128-bit IRTemp */
3305    if (e->tag == Iex_RdTmp) {
3306       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
3307       return;
3308    }
3309 
3310    /* 128-bit GET */
3311    if (e->tag == Iex_Get) {
3312       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3313                                        GuestStatePtr(mode64) );
3314       PPCAMode* am_addr4 = advance4(env, am_addr);
3315       HReg tLo = newVRegI(env);
3316       HReg tHi = newVRegI(env);
3317 
3318       addInstr(env, PPCInstr_Load( 8, tHi, am_addr,  mode64));
3319       addInstr(env, PPCInstr_Load( 8, tLo, am_addr4, mode64));
3320       *rHi = tHi;
3321       *rLo = tLo;
3322       return;
3323    }
3324 
3325    /* --------- BINARY ops --------- */
3326    if (e->tag == Iex_Binop) {
3327       switch (e->Iex.Binop.op) {
3328       /* 64 x 64 -> 128 multiply */
3329       case Iop_MullU64:
3330       case Iop_MullS64: {
3331          HReg     tLo     = newVRegI(env);
3332          HReg     tHi     = newVRegI(env);
3333          Bool     syned   = toBool(e->Iex.Binop.op == Iop_MullS64);
3334          HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3335          HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
3336          addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
3337                                      False/*lo64*/, False/*64bit mul*/,
3338                                      tLo, r_srcL, r_srcR));
3339          addInstr(env, PPCInstr_MulL(syned,
3340                                      True/*hi64*/, False/*64bit mul*/,
3341                                      tHi, r_srcL, r_srcR));
3342          *rHi = tHi;
3343          *rLo = tLo;
3344          return;
3345       }
3346 
3347       /* 64HLto128(e1,e2) */
3348       case Iop_64HLto128:
3349          *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3350          *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
3351          return;
3352       default:
3353          break;
3354       }
3355    } /* if (e->tag == Iex_Binop) */
3356 
3357 
3358    /* --------- UNARY ops --------- */
3359    if (e->tag == Iex_Unop) {
3360       switch (e->Iex.Unop.op) {
3361       default:
3362          break;
3363       }
3364    } /* if (e->tag == Iex_Unop) */
3365 
3366    vex_printf("iselInt128Expr(ppc64): No such tag(%u)\n", e->tag);
3367    ppIRExpr(e);
3368    vpanic("iselInt128Expr(ppc64)");
3369 }
3370 
3371 
3372 /*---------------------------------------------------------*/
3373 /*--- ISEL: Integer expressions (64 bit)                ---*/
3374 /*---------------------------------------------------------*/
3375 
3376 /* 32-bit mode ONLY: compute a 128-bit value into a register quad */
iselInt128Expr_to_32x4(HReg * rHi,HReg * rMedHi,HReg * rMedLo,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3377 static void iselInt128Expr_to_32x4 ( HReg* rHi, HReg* rMedHi, HReg* rMedLo,
3378                                      HReg* rLo, ISelEnv* env, const IRExpr* e,
3379                                      IREndness IEndianess )
3380 {
3381    vassert(!env->mode64);
3382    iselInt128Expr_to_32x4_wrk(rHi, rMedHi, rMedLo, rLo, env, e, IEndianess);
3383 #  if 0
3384    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3385 #  endif
3386    vassert(hregClass(*rHi) == HRcInt32);
3387    vassert(hregIsVirtual(*rHi));
3388    vassert(hregClass(*rMedHi) == HRcInt32);
3389    vassert(hregIsVirtual(*rMedHi));
3390    vassert(hregClass(*rMedLo) == HRcInt32);
3391    vassert(hregIsVirtual(*rMedLo));
3392    vassert(hregClass(*rLo) == HRcInt32);
3393    vassert(hregIsVirtual(*rLo));
3394 }
3395 
iselInt128Expr_to_32x4_wrk(HReg * rHi,HReg * rMedHi,HReg * rMedLo,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3396 static void iselInt128Expr_to_32x4_wrk ( HReg* rHi, HReg* rMedHi,
3397                                          HReg* rMedLo, HReg* rLo,
3398                                          ISelEnv* env, const IRExpr* e,
3399                                          IREndness IEndianess )
3400 {
3401    vassert(e);
3402    vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
3403 
3404    /* read 128-bit IRTemp */
3405    if (e->tag == Iex_RdTmp) {
3406       lookupIRTempQuad( rHi, rMedHi, rMedLo, rLo, env, e->Iex.RdTmp.tmp);
3407       return;
3408    }
3409 
3410    if (e->tag == Iex_Binop) {
3411 
3412       IROp op_binop = e->Iex.Binop.op;
3413       switch (op_binop) {
3414       case Iop_64HLto128:
3415          iselInt64Expr(rHi, rMedHi, env, e->Iex.Binop.arg1, IEndianess);
3416          iselInt64Expr(rMedLo, rLo, env, e->Iex.Binop.arg2, IEndianess);
3417          return;
3418       default:
3419          vex_printf("iselInt128Expr_to_32x4_wrk: Binop case 0x%x not found\n",
3420                     op_binop);
3421          break;
3422       }
3423    }
3424 
3425    vex_printf("iselInt128Expr_to_32x4_wrk: e->tag 0x%x not found\n", e->tag);
3426    return;
3427 }
3428 
3429 /* 32-bit mode ONLY: compute a 64-bit value into a register pair,
3430    which is returned as the first two parameters.  As with
3431    iselIntExpr_R, these may be either real or virtual regs; in any
3432    case they must not be changed by subsequent code emitted by the
3433    caller.  */
3434 
iselInt64Expr(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3435 static void iselInt64Expr ( HReg* rHi, HReg* rLo,
3436                             ISelEnv* env, const IRExpr* e,
3437                             IREndness IEndianess )
3438 {
3439    vassert(!env->mode64);
3440    iselInt64Expr_wrk(rHi, rLo, env, e, IEndianess);
3441 #  if 0
3442    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3443 #  endif
3444    vassert(hregClass(*rHi) == HRcInt32);
3445    vassert(hregIsVirtual(*rHi));
3446    vassert(hregClass(*rLo) == HRcInt32);
3447    vassert(hregIsVirtual(*rLo));
3448 }
3449 
3450 /* DO NOT CALL THIS DIRECTLY ! */
iselInt64Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3451 static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
3452                                 ISelEnv* env, const IRExpr* e,
3453                                 IREndness IEndianess )
3454 {
3455    vassert(e);
3456    vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
3457 
3458    /* 64-bit load */
3459    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
3460       HReg tLo    = newVRegI(env);
3461       HReg tHi    = newVRegI(env);
3462       HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr, IEndianess);
3463       vassert(!env->mode64);
3464       addInstr(env, PPCInstr_Load( 4/*byte-load*/,
3465                                    tHi, PPCAMode_IR( 0, r_addr ),
3466                                    False/*32-bit insn please*/) );
3467       addInstr(env, PPCInstr_Load( 4/*byte-load*/,
3468                                    tLo, PPCAMode_IR( 4, r_addr ),
3469                                    False/*32-bit insn please*/) );
3470       *rHi = tHi;
3471       *rLo = tLo;
3472       return;
3473    }
3474 
3475    /* 64-bit literal */
3476    if (e->tag == Iex_Const) {
3477       ULong w64 = e->Iex.Const.con->Ico.U64;
3478       UInt  wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
3479       UInt  wLo = ((UInt)w64) & 0xFFFFFFFF;
3480       HReg  tLo = newVRegI(env);
3481       HReg  tHi = newVRegI(env);
3482       vassert(e->Iex.Const.con->tag == Ico_U64);
3483       addInstr(env, PPCInstr_LI(tHi, (Long)(Int)wHi, False/*mode32*/));
3484       addInstr(env, PPCInstr_LI(tLo, (Long)(Int)wLo, False/*mode32*/));
3485       *rHi = tHi;
3486       *rLo = tLo;
3487       return;
3488    }
3489 
3490    /* read 64-bit IRTemp */
3491    if (e->tag == Iex_RdTmp) {
3492       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
3493       return;
3494    }
3495 
3496    /* 64-bit GET */
3497    if (e->tag == Iex_Get) {
3498       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3499                                        GuestStatePtr(False/*mode32*/) );
3500       PPCAMode* am_addr4 = advance4(env, am_addr);
3501       HReg tLo = newVRegI(env);
3502       HReg tHi = newVRegI(env);
3503       addInstr(env, PPCInstr_Load( 4, tHi, am_addr,  False/*mode32*/ ));
3504       addInstr(env, PPCInstr_Load( 4, tLo, am_addr4, False/*mode32*/ ));
3505       *rHi = tHi;
3506       *rLo = tLo;
3507       return;
3508    }
3509 
3510    /* --------- CCALL --------- */
3511    if(e->tag == Iex_CCall) {
3512       IRType ty = typeOfIRExpr(env->type_env,e);
3513       Bool mode64 = env->mode64;
3514 
3515       vassert(ty == e->Iex.CCall.retty); /* well-formedness of IR */
3516 
3517       /* be very restrictive for now.  Only 32-bit ints allowed for
3518          args, and 32 bits or host machine word for return type. */
3519       vassert(!(ty == Ity_I32 || (mode64 && ty == Ity_I64)));
3520 
3521       /* Marshal args, do the call, clear stack. */
3522       UInt   addToSp = 0;
3523       RetLoc rloc    = mk_RetLoc_INVALID();
3524       doHelperCall( &addToSp, &rloc, env, NULL/*guard*/,
3525                     e->Iex.CCall.cee, e->Iex.CCall.retty, e->Iex.CCall.args,
3526                     IEndianess );
3527       vassert(is_sane_RetLoc(rloc));
3528 
3529       vassert(rloc.pri == RLPri_2Int);
3530       vassert(addToSp == 0);
3531 
3532       /* GPR3 now holds the destination address from Pin_Goto */
3533       HReg r_dst = newVRegI(env);
3534       addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
3535       *rHi = r_dst;
3536       *rLo = r_dst;
3537       return;
3538    }
3539 
3540    /* 64-bit ITE */
3541    if (e->tag == Iex_ITE) { // VFD
3542       HReg e0Lo, e0Hi, eXLo, eXHi;
3543       iselInt64Expr(&eXHi, &eXLo, env, e->Iex.ITE.iftrue, IEndianess);
3544       iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.ITE.iffalse, IEndianess);
3545       HReg tLo = newVRegI(env);
3546       HReg tHi = newVRegI(env);
3547       addInstr(env, mk_iMOVds_RR(tHi,e0Hi));
3548       addInstr(env, mk_iMOVds_RR(tLo,e0Lo));
3549       PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond, IEndianess);
3550       addInstr(env, PPCInstr_CMov(cc,tHi,PPCRI_Reg(eXHi)));
3551       addInstr(env, PPCInstr_CMov(cc,tLo,PPCRI_Reg(eXLo)));
3552       *rHi = tHi;
3553       *rLo = tLo;
3554       return;
3555    }
3556 
3557    /* --------- BINARY ops --------- */
3558    if (e->tag == Iex_Binop) {
3559       IROp op_binop = e->Iex.Binop.op;
3560       switch (op_binop) {
3561          /* 32 x 32 -> 64 multiply */
3562          case Iop_MullU32:
3563          case Iop_MullS32: {
3564             HReg     tLo     = newVRegI(env);
3565             HReg     tHi     = newVRegI(env);
3566             Bool     syned   = toBool(op_binop == Iop_MullS32);
3567             HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1,
3568                                               IEndianess);
3569             HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2,
3570                                               IEndianess);
3571             addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
3572                                         False/*lo32*/, True/*32bit mul*/,
3573                                         tLo, r_srcL, r_srcR));
3574             addInstr(env, PPCInstr_MulL(syned,
3575                                         True/*hi32*/, True/*32bit mul*/,
3576                                         tHi, r_srcL, r_srcR));
3577             *rHi = tHi;
3578             *rLo = tLo;
3579             return;
3580          }
3581 
3582          /* Or64/And64/Xor64 */
3583          case Iop_Or64:
3584          case Iop_And64:
3585          case Iop_Xor64: {
3586             HReg xLo, xHi, yLo, yHi;
3587             HReg tLo = newVRegI(env);
3588             HReg tHi = newVRegI(env);
3589             PPCAluOp op = (op_binop == Iop_Or64) ? Palu_OR :
3590                           (op_binop == Iop_And64) ? Palu_AND : Palu_XOR;
3591             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1, IEndianess);
3592             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2, IEndianess);
3593             addInstr(env, PPCInstr_Alu(op, tHi, xHi, PPCRH_Reg(yHi)));
3594             addInstr(env, PPCInstr_Alu(op, tLo, xLo, PPCRH_Reg(yLo)));
3595             *rHi = tHi;
3596             *rLo = tLo;
3597             return;
3598          }
3599 
3600          /* Add64 */
3601          case Iop_Add64: {
3602             HReg xLo, xHi, yLo, yHi;
3603             HReg tLo = newVRegI(env);
3604             HReg tHi = newVRegI(env);
3605             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1, IEndianess);
3606             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2, IEndianess);
3607             addInstr(env, PPCInstr_AddSubC( True/*add*/, True /*set carry*/,
3608                                             tLo, xLo, yLo));
3609             addInstr(env, PPCInstr_AddSubC( True/*add*/, False/*read carry*/,
3610                                             tHi, xHi, yHi));
3611             *rHi = tHi;
3612             *rLo = tLo;
3613             return;
3614          }
3615 
3616          /* 32HLto64(e1,e2) */
3617          case Iop_32HLto64:
3618             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3619             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
3620             return;
3621 
3622          /* F64toI64[S|U] */
3623          case Iop_F64toI64S: case Iop_F64toI64U: {
3624             HReg      tLo     = newVRegI(env);
3625             HReg      tHi     = newVRegI(env);
3626             HReg      r1      = StackFramePtr(env->mode64);
3627             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3628             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3629             HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2,
3630                                             IEndianess);
3631             HReg      ftmp    = newVRegF(env);
3632 
3633             vassert(!env->mode64);
3634             /* Set host rounding mode */
3635             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
3636 
3637             sub_from_sp( env, 16 );
3638             addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
3639                                           (op_binop == Iop_F64toI64S) ? True : False,
3640                                           True, ftmp, fsrc));
3641             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
3642             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3643             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3644             add_to_sp( env, 16 );
3645 
3646             ///* Restore default FPU rounding. */
3647             //set_FPU_rounding_default( env );
3648             *rHi = tHi;
3649             *rLo = tLo;
3650             return;
3651          }
3652          case Iop_D64toI64S: {
3653             HReg      tLo     = newVRegI(env);
3654             HReg      tHi     = newVRegI(env);
3655             HReg      r1      = StackFramePtr(env->mode64);
3656             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3657             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3658             HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
3659             HReg tmp    = newVRegF(env);
3660 
3661             vassert(!env->mode64);
3662             set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
3663             addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTFIX, tmp, fr_src));
3664 
3665             sub_from_sp( env, 16 );
3666             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
3667             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3668             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3669             add_to_sp( env, 16 );
3670             *rHi = tHi;
3671             *rLo = tLo;
3672             return;
3673          }
3674          case Iop_D128toI64S: {
3675             PPCFpOp fpop = Pfp_DCTFIXQ;
3676             HReg r_srcHi = newVRegF(env);
3677             HReg r_srcLo = newVRegF(env);
3678             HReg tLo     = newVRegI(env);
3679             HReg tHi     = newVRegI(env);
3680             HReg ftmp    = newVRegF(env);
3681             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3682             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
3683 
3684             set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
3685             iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
3686                            IEndianess);
3687             addInstr(env, PPCInstr_DfpD128toD64(fpop, ftmp, r_srcHi, r_srcLo));
3688 
3689             // put the D64 result into an integer register pair
3690             sub_from_sp( env, 16 );
3691             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
3692             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3693             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3694             add_to_sp( env, 16 );
3695             *rHi = tHi;
3696             *rLo = tLo;
3697             return;
3698          }
3699          default:
3700             break;
3701       }
3702    } /* if (e->tag == Iex_Binop) */
3703 
3704 
3705    /* --------- UNARY ops --------- */
3706    if (e->tag == Iex_Unop) {
3707       switch (e->Iex.Unop.op) {
3708 
3709       /* CmpwNEZ64(e) */
3710       case Iop_CmpwNEZ64: {
3711          HReg argHi, argLo;
3712          HReg tmp1  = newVRegI(env);
3713          HReg tmp2  = newVRegI(env);
3714          iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg, IEndianess);
3715          /* tmp1 = argHi | argLo */
3716          addInstr(env, PPCInstr_Alu(Palu_OR, tmp1, argHi, PPCRH_Reg(argLo)));
3717          /* tmp2 = (tmp1 | -tmp1) >>s 31 */
3718          addInstr(env, PPCInstr_Unary(Pun_NEG,tmp2,tmp1));
3719          addInstr(env, PPCInstr_Alu(Palu_OR, tmp2, tmp2, PPCRH_Reg(tmp1)));
3720          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3721                                      tmp2, tmp2, PPCRH_Imm(False, 31)));
3722          *rHi = tmp2;
3723          *rLo = tmp2; /* yes, really tmp2 */
3724          return;
3725       }
3726 
3727       /* Left64 */
3728       case Iop_Left64: {
3729          HReg argHi, argLo;
3730          HReg zero32 = newVRegI(env);
3731          HReg resHi  = newVRegI(env);
3732          HReg resLo  = newVRegI(env);
3733          iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg, IEndianess);
3734          vassert(env->mode64 == False);
3735          addInstr(env, PPCInstr_LI(zero32, 0, env->mode64));
3736          /* resHi:resLo = - argHi:argLo */
3737          addInstr(env, PPCInstr_AddSubC( False/*sub*/, True/*set carry*/,
3738                                          resLo, zero32, argLo ));
3739          addInstr(env, PPCInstr_AddSubC( False/*sub*/, False/*read carry*/,
3740                                          resHi, zero32, argHi ));
3741          /* resHi:resLo |= srcHi:srcLo */
3742          addInstr(env, PPCInstr_Alu(Palu_OR, resLo, resLo, PPCRH_Reg(argLo)));
3743          addInstr(env, PPCInstr_Alu(Palu_OR, resHi, resHi, PPCRH_Reg(argHi)));
3744          *rHi = resHi;
3745          *rLo = resLo;
3746          return;
3747       }
3748 
3749       /* 32Sto64(e) */
3750       case Iop_32Sto64: {
3751          HReg tHi = newVRegI(env);
3752          HReg src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
3753          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3754                                      tHi, src, PPCRH_Imm(False,31)));
3755          *rHi = tHi;
3756          *rLo = src;
3757          return;
3758       }
3759       case Iop_ExtractExpD64: {
3760          HReg tmp    = newVRegF(env);
3761          HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
3762          HReg      tLo     = newVRegI(env);
3763          HReg      tHi     = newVRegI(env);
3764          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3765          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
3766 
3767          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DXEX, tmp, fr_src));
3768 
3769          // put the D64 result into a integer register pair
3770          sub_from_sp( env, 16 );
3771          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
3772          addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3773          addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3774          add_to_sp( env, 16 );
3775          *rHi = tHi;
3776          *rLo = tLo;
3777          return;
3778       }
3779       case Iop_ExtractExpD128: {
3780          HReg      r_srcHi;
3781          HReg      r_srcLo;
3782          HReg      tmp     = newVRegF(env);
3783          HReg      tLo     = newVRegI(env);
3784          HReg      tHi     = newVRegI(env);
3785          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3786          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
3787 
3788          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Unop.arg, IEndianess);
3789          addInstr(env, PPCInstr_ExtractExpD128(Pfp_DXEXQ, tmp,
3790                                                   r_srcHi, r_srcLo));
3791 
3792          // put the D64 result into a integer register pair
3793          sub_from_sp( env, 16 );
3794          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
3795          addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3796          addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3797          add_to_sp( env, 16 );
3798          *rHi = tHi;
3799          *rLo = tLo;
3800          return;
3801       }
3802 
3803       /* 32Uto64(e) */
3804       case Iop_32Uto64: {
3805          HReg tHi = newVRegI(env);
3806          HReg tLo = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
3807          addInstr(env, PPCInstr_LI(tHi, 0, False/*mode32*/));
3808          *rHi = tHi;
3809          *rLo = tLo;
3810          return;
3811       }
3812 
3813       case Iop_128to64: {
3814          /* Narrow, return the low 64-bit half as a 32-bit
3815           * register pair */
3816          HReg r_Hi    = INVALID_HREG;
3817          HReg r_MedHi = INVALID_HREG;
3818          HReg r_MedLo = INVALID_HREG;
3819          HReg r_Lo    = INVALID_HREG;
3820 
3821          iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
3822                                 env, e->Iex.Unop.arg, IEndianess);
3823          *rHi = r_MedLo;
3824          *rLo = r_Lo;
3825          return;
3826       }
3827 
3828       case Iop_128HIto64: {
3829          /* Narrow, return the high 64-bit half as a 32-bit
3830           *  register pair */
3831          HReg r_Hi    = INVALID_HREG;
3832          HReg r_MedHi = INVALID_HREG;
3833          HReg r_MedLo = INVALID_HREG;
3834          HReg r_Lo    = INVALID_HREG;
3835 
3836          iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
3837                                 env, e->Iex.Unop.arg, IEndianess);
3838          *rHi = r_Hi;
3839          *rLo = r_MedHi;
3840          return;
3841       }
3842 
3843       /* V128{HI}to64 */
3844       case Iop_V128HIto64:
3845       case Iop_V128to64: {
3846          HReg r_aligned16;
3847          Int  off = e->Iex.Unop.op==Iop_V128HIto64 ? 0 : 8;
3848          HReg tLo = newVRegI(env);
3849          HReg tHi = newVRegI(env);
3850          HReg vec = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
3851          PPCAMode *am_off0, *am_offLO, *am_offHI;
3852          sub_from_sp( env, 32 );     // Move SP down 32 bytes
3853 
3854          // get a quadword aligned address within our stack space
3855          r_aligned16 = get_sp_aligned16( env );
3856          am_off0  = PPCAMode_IR( 0,     r_aligned16 );
3857          am_offHI = PPCAMode_IR( off,   r_aligned16 );
3858          am_offLO = PPCAMode_IR( off+4, r_aligned16 );
3859 
3860          // store as Vec128
3861          addInstr(env,
3862                   PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
3863 
3864          // load hi,lo words (of hi/lo half of vec) as Ity_I32's
3865          addInstr(env,
3866                   PPCInstr_Load( 4, tHi, am_offHI, False/*mode32*/ ));
3867          addInstr(env,
3868                   PPCInstr_Load( 4, tLo, am_offLO, False/*mode32*/ ));
3869 
3870          add_to_sp( env, 32 );       // Reset SP
3871          *rHi = tHi;
3872          *rLo = tLo;
3873          return;
3874       }
3875 
3876       /* could do better than this, but for now ... */
3877       case Iop_1Sto64: {
3878          HReg tLo = newVRegI(env);
3879          HReg tHi = newVRegI(env);
3880          PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
3881          addInstr(env, PPCInstr_Set(cond,tLo));
3882          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
3883                                      tLo, tLo, PPCRH_Imm(False,31)));
3884          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3885                                      tLo, tLo, PPCRH_Imm(False,31)));
3886          addInstr(env, mk_iMOVds_RR(tHi, tLo));
3887          *rHi = tHi;
3888          *rLo = tLo;
3889          return;
3890       }
3891 
3892       case Iop_Not64: {
3893          HReg xLo, xHi;
3894          HReg tmpLo = newVRegI(env);
3895          HReg tmpHi = newVRegI(env);
3896          iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg, IEndianess);
3897          addInstr(env, PPCInstr_Unary(Pun_NOT,tmpLo,xLo));
3898          addInstr(env, PPCInstr_Unary(Pun_NOT,tmpHi,xHi));
3899          *rHi = tmpHi;
3900          *rLo = tmpLo;
3901          return;
3902       }
3903 
3904       /* ReinterpF64asI64(e) */
3905       /* Given an IEEE754 double, produce an I64 with the same bit
3906          pattern. */
3907       case Iop_ReinterpF64asI64: {
3908          PPCAMode *am_addr0, *am_addr1;
3909          HReg fr_src  = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
3910          HReg r_dstLo = newVRegI(env);
3911          HReg r_dstHi = newVRegI(env);
3912 
3913          sub_from_sp( env, 16 );     // Move SP down 16 bytes
3914          am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
3915          am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
3916 
3917          // store as F64
3918          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
3919                                         fr_src, am_addr0 ));
3920 
3921          // load hi,lo as Ity_I32's
3922          addInstr(env, PPCInstr_Load( 4, r_dstHi,
3923                                       am_addr0, False/*mode32*/ ));
3924          addInstr(env, PPCInstr_Load( 4, r_dstLo,
3925                                       am_addr1, False/*mode32*/ ));
3926          *rHi = r_dstHi;
3927          *rLo = r_dstLo;
3928 
3929          add_to_sp( env, 16 );       // Reset SP
3930          return;
3931       }
3932 
3933       case Iop_ReinterpD64asI64: {
3934          HReg fr_src  = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
3935          PPCAMode *am_addr0, *am_addr1;
3936          HReg r_dstLo = newVRegI(env);
3937          HReg r_dstHi = newVRegI(env);
3938 
3939 
3940          sub_from_sp( env, 16 );     // Move SP down 16 bytes
3941          am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
3942          am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
3943 
3944          // store as D64
3945          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
3946                                         fr_src, am_addr0 ));
3947 
3948          // load hi,lo as Ity_I32's
3949          addInstr(env, PPCInstr_Load( 4, r_dstHi,
3950                                       am_addr0, False/*mode32*/ ));
3951          addInstr(env, PPCInstr_Load( 4, r_dstLo,
3952                                       am_addr1, False/*mode32*/ ));
3953          *rHi = r_dstHi;
3954          *rLo = r_dstLo;
3955 
3956          add_to_sp( env, 16 );       // Reset SP
3957 
3958          return;
3959       }
3960 
3961       case Iop_BCDtoDPB: {
3962          PPCCondCode cc;
3963          UInt        argiregs;
3964          HReg        argregs[2];
3965          Int         argreg;
3966          HReg        tLo = newVRegI(env);
3967          HReg        tHi = newVRegI(env);
3968          HReg        tmpHi;
3969          HReg        tmpLo;
3970          Bool        mode64 = env->mode64;
3971 
3972          argregs[0] = hregPPC_GPR3(mode64);
3973          argregs[1] = hregPPC_GPR4(mode64);
3974 
3975          argiregs = 0;
3976          argreg = 0;
3977 
3978          iselInt64Expr( &tmpHi, &tmpLo, env, e->Iex.Unop.arg, IEndianess );
3979 
3980          argiregs |= ( 1 << (argreg+3 ) );
3981          addInstr( env, mk_iMOVds_RR( argregs[argreg++], tmpHi ) );
3982 
3983          argiregs |= ( 1 << (argreg+3 ) );
3984          addInstr( env, mk_iMOVds_RR( argregs[argreg], tmpLo ) );
3985 
3986          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
3987 
3988          if (IEndianess == Iend_LE) {
3989              addInstr( env, PPCInstr_Call( cc, (Addr)h_calc_BCDtoDPB,
3990                                            argiregs,
3991                                            mk_RetLoc_simple(RLPri_2Int) ) );
3992          } else {
3993              Addr64 target;
3994              target = mode64 ? (Addr)h_calc_BCDtoDPB :
3995                toUInt( (Addr)h_calc_BCDtoDPB );
3996              addInstr( env, PPCInstr_Call( cc, target,
3997                                            argiregs,
3998                                            mk_RetLoc_simple(RLPri_2Int) ) );
3999          }
4000 
4001          addInstr( env, mk_iMOVds_RR( tHi, argregs[argreg-1] ) );
4002          addInstr( env, mk_iMOVds_RR( tLo, argregs[argreg] ) );
4003 
4004          *rHi = tHi;
4005          *rLo = tLo;
4006          return;
4007       }
4008 
4009       case Iop_DPBtoBCD: {
4010          PPCCondCode cc;
4011          UInt        argiregs;
4012          HReg        argregs[2];
4013          Int         argreg;
4014          HReg        tLo = newVRegI(env);
4015          HReg        tHi = newVRegI(env);
4016          HReg        tmpHi;
4017          HReg        tmpLo;
4018          Bool        mode64 = env->mode64;
4019 
4020          argregs[0] = hregPPC_GPR3(mode64);
4021          argregs[1] = hregPPC_GPR4(mode64);
4022 
4023          argiregs = 0;
4024          argreg = 0;
4025 
4026          iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg, IEndianess);
4027 
4028          argiregs |= (1 << (argreg+3));
4029          addInstr(env, mk_iMOVds_RR( argregs[argreg++], tmpHi ));
4030 
4031          argiregs |= (1 << (argreg+3));
4032          addInstr(env, mk_iMOVds_RR( argregs[argreg], tmpLo));
4033 
4034          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
4035 
4036          if (IEndianess == Iend_LE) {
4037              addInstr(env, PPCInstr_Call( cc, (Addr)h_calc_DPBtoBCD,
4038                                           argiregs,
4039                                           mk_RetLoc_simple(RLPri_2Int) ) );
4040          } else {
4041              Addr64 target;
4042              target = mode64 ? (Addr)h_calc_DPBtoBCD :
4043                toUInt( (Addr)h_calc_DPBtoBCD );
4044              addInstr(env, PPCInstr_Call( cc, target, argiregs,
4045                                           mk_RetLoc_simple(RLPri_2Int) ) );
4046          }
4047 
4048          addInstr(env, mk_iMOVds_RR(tHi, argregs[argreg-1]));
4049          addInstr(env, mk_iMOVds_RR(tLo, argregs[argreg]));
4050 
4051          *rHi = tHi;
4052          *rLo = tLo;
4053          return;
4054       }
4055 
4056       default:
4057          break;
4058       }
4059    } /* if (e->tag == Iex_Unop) */
4060 
4061    vex_printf("iselInt64Expr(ppc): No such tag(%u)\n", e->tag);
4062    ppIRExpr(e);
4063    vpanic("iselInt64Expr(ppc)");
4064 }
4065 
4066 
4067 /*---------------------------------------------------------*/
4068 /*--- ISEL: Floating point expressions (32 bit)         ---*/
4069 /*---------------------------------------------------------*/
4070 
4071 /* Nothing interesting here; really just wrappers for
4072    64-bit stuff. */
4073 
iselFltExpr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4074 static HReg iselFltExpr ( ISelEnv* env, const IRExpr* e, IREndness IEndianess )
4075 {
4076   HReg r = iselFltExpr_wrk( env, e, IEndianess );
4077 #  if 0
4078    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4079 #  endif
4080    vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
4081    vassert(hregIsVirtual(r));
4082    return r;
4083 }
4084 
4085 /* DO NOT CALL THIS DIRECTLY */
iselFltExpr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4086 static HReg iselFltExpr_wrk ( ISelEnv* env, const IRExpr* e,
4087                               IREndness IEndianess )
4088 {
4089    Bool        mode64 = env->mode64;
4090 
4091    IRType ty = typeOfIRExpr(env->type_env,e);
4092    vassert(ty == Ity_F32);
4093 
4094    if (e->tag == Iex_RdTmp) {
4095       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
4096    }
4097 
4098    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
4099       PPCAMode* am_addr;
4100       HReg r_dst = newVRegF(env);
4101       vassert(e->Iex.Load.ty == Ity_F32);
4102       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F32/*xfer*/,
4103                                    IEndianess);
4104       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
4105       return r_dst;
4106    }
4107 
4108    if (e->tag == Iex_Get) {
4109       HReg r_dst = newVRegF(env);
4110       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
4111                                        GuestStatePtr(env->mode64) );
4112       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4, r_dst, am_addr ));
4113       return r_dst;
4114    }
4115 
4116    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
4117       /* This is quite subtle.  The only way to do the relevant
4118          truncation is to do a single-precision store and then a
4119          double precision load to get it back into a register.  The
4120          problem is, if the data is then written to memory a second
4121          time, as in
4122 
4123             STbe(...) = TruncF64asF32(...)
4124 
4125          then will the second truncation further alter the value?  The
4126          answer is no: flds (as generated here) followed by fsts
4127          (generated for the STbe) is the identity function on 32-bit
4128          floats, so we are safe.
4129 
4130          Another upshot of this is that if iselStmt can see the
4131          entirety of
4132 
4133             STbe(...) = TruncF64asF32(arg)
4134 
4135          then it can short circuit having to deal with TruncF64asF32
4136          individually; instead just compute arg into a 64-bit FP
4137          register and do 'fsts' (since that itself does the
4138          truncation).
4139 
4140          We generate pretty poor code here (should be ok both for
4141          32-bit and 64-bit mode); but it is expected that for the most
4142          part the latter optimisation will apply and hence this code
4143          will not often be used.
4144       */
4145       HReg      fsrc    = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
4146       HReg      fdst    = newVRegF(env);
4147       PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4148 
4149       sub_from_sp( env, 16 );
4150       // store as F32, hence truncating
4151       addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
4152                                      fsrc, zero_r1 ));
4153       // and reload.  Good huh?! (sigh)
4154       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4,
4155                                      fdst, zero_r1 ));
4156       add_to_sp( env, 16 );
4157       return fdst;
4158    }
4159 
4160    if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64UtoF32) {
4161       if (mode64) {
4162          HReg fdst = newVRegF(env);
4163          HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
4164          HReg r1   = StackFramePtr(env->mode64);
4165          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
4166 
4167          /* Set host rounding mode */
4168          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4169 
4170          sub_from_sp( env, 16 );
4171 
4172          addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
4173          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
4174          addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
4175                                        False, False,
4176                                        fdst, fdst));
4177 
4178          add_to_sp( env, 16 );
4179 
4180          ///* Restore default FPU rounding. */
4181          //set_FPU_rounding_default( env );
4182          return fdst;
4183       } else {
4184          /* 32-bit mode */
4185          HReg fdst = newVRegF(env);
4186          HReg isrcHi, isrcLo;
4187          HReg r1   = StackFramePtr(env->mode64);
4188          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
4189          PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
4190 
4191          iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2, IEndianess);
4192 
4193          /* Set host rounding mode */
4194          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4195 
4196          sub_from_sp( env, 16 );
4197 
4198          addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
4199          addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
4200          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
4201          addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
4202                                        False, False,
4203                                        fdst, fdst));
4204 
4205          add_to_sp( env, 16 );
4206 
4207          ///* Restore default FPU rounding. */
4208          //set_FPU_rounding_default( env );
4209          return fdst;
4210       }
4211 
4212    }
4213 
4214    vex_printf("iselFltExpr(ppc): No such tag(%u)\n", e->tag);
4215    ppIRExpr(e);
4216    vpanic("iselFltExpr_wrk(ppc)");
4217 }
4218 
4219 
4220 /*---------------------------------------------------------*/
4221 /*--- ISEL: Floating point expressions (64 bit)         ---*/
4222 /*---------------------------------------------------------*/
4223 
4224 /* Compute a 64-bit floating point value into a register, the identity
4225    of which is returned.  As with iselIntExpr_R, the reg may be either
4226    real or virtual; in any case it must not be changed by subsequent
4227    code emitted by the caller.  */
4228 
4229 /* IEEE 754 formats.  From http://www.freesoft.org/CIE/RFC/1832/32.htm:
4230 
4231     Type                  S (1 bit)   E (11 bits)   F (52 bits)
4232     ----                  ---------   -----------   -----------
4233     signalling NaN        u           2047 (max)    .0uuuuu---u
4234                                                     (with at least
4235                                                      one 1 bit)
4236     quiet NaN             u           2047 (max)    .1uuuuu---u
4237 
4238     negative infinity     1           2047 (max)    .000000---0
4239 
4240     positive infinity     0           2047 (max)    .000000---0
4241 
4242     negative zero         1           0             .000000---0
4243 
4244     positive zero         0           0             .000000---0
4245 */
4246 
iselDblExpr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4247 static HReg iselDblExpr ( ISelEnv* env, const IRExpr* e, IREndness IEndianess )
4248 {
4249    HReg r = iselDblExpr_wrk( env, e, IEndianess );
4250 #  if 0
4251    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4252 #  endif
4253    vassert(hregClass(r) == HRcFlt64);
4254    vassert(hregIsVirtual(r));
4255    return r;
4256 }
4257 
4258 /* DO NOT CALL THIS DIRECTLY */
iselDblExpr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4259 static HReg iselDblExpr_wrk ( ISelEnv* env, const IRExpr* e,
4260                               IREndness IEndianess )
4261 {
4262    Bool mode64 = env->mode64;
4263    IRType ty = typeOfIRExpr(env->type_env,e);
4264    vassert(e);
4265    vassert(ty == Ity_F64);
4266 
4267    if (e->tag == Iex_RdTmp) {
4268       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
4269    }
4270 
4271    /* --------- LITERAL --------- */
4272    if (e->tag == Iex_Const) {
4273       union { UInt u32x2[2]; ULong u64; Double f64; } u;
4274       vassert(sizeof(u) == 8);
4275       vassert(sizeof(u.u64) == 8);
4276       vassert(sizeof(u.f64) == 8);
4277       vassert(sizeof(u.u32x2) == 8);
4278 
4279       if (e->Iex.Const.con->tag == Ico_F64) {
4280          u.f64 = e->Iex.Const.con->Ico.F64;
4281       }
4282       else if (e->Iex.Const.con->tag == Ico_F64i) {
4283          u.u64 = e->Iex.Const.con->Ico.F64i;
4284       }
4285       else
4286          vpanic("iselDblExpr(ppc): const");
4287 
4288       if (!mode64) {
4289          HReg r_srcHi = newVRegI(env);
4290          HReg r_srcLo = newVRegI(env);
4291          addInstr(env, PPCInstr_LI(r_srcHi, u.u32x2[0], mode64));
4292          addInstr(env, PPCInstr_LI(r_srcLo, u.u32x2[1], mode64));
4293          return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
4294       } else { // mode64
4295          HReg r_src = newVRegI(env);
4296          addInstr(env, PPCInstr_LI(r_src, u.u64, mode64));
4297          return mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
4298       }
4299    }
4300 
4301    /* --------- LOAD --------- */
4302    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
4303       HReg r_dst = newVRegF(env);
4304       PPCAMode* am_addr;
4305       vassert(e->Iex.Load.ty == Ity_F64);
4306       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F64/*xfer*/,
4307                                    IEndianess);
4308       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
4309       return r_dst;
4310    }
4311 
4312    /* --------- GET --------- */
4313    if (e->tag == Iex_Get) {
4314       HReg r_dst = newVRegF(env);
4315       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
4316                                        GuestStatePtr(mode64) );
4317       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ));
4318       return r_dst;
4319    }
4320 
4321    /* --------- OPS --------- */
4322    if (e->tag == Iex_Qop) {
4323       PPCFpOp fpop = Pfp_INVALID;
4324       switch (e->Iex.Qop.details->op) {
4325          case Iop_MAddF64:    fpop = Pfp_MADDD; break;
4326          case Iop_MAddF64r32: fpop = Pfp_MADDS; break;
4327          case Iop_MSubF64:    fpop = Pfp_MSUBD; break;
4328          case Iop_MSubF64r32: fpop = Pfp_MSUBS; break;
4329          default: break;
4330       }
4331       if (fpop != Pfp_INVALID) {
4332          HReg r_dst  = newVRegF(env);
4333          HReg r_srcML  = iselDblExpr(env, e->Iex.Qop.details->arg2,
4334                                      IEndianess);
4335          HReg r_srcMR  = iselDblExpr(env, e->Iex.Qop.details->arg3,
4336                                      IEndianess);
4337          HReg r_srcAcc = iselDblExpr(env, e->Iex.Qop.details->arg4,
4338                                      IEndianess);
4339          set_FPU_rounding_mode( env, e->Iex.Qop.details->arg1, IEndianess );
4340          addInstr(env, PPCInstr_FpMulAcc(fpop, r_dst,
4341                                                r_srcML, r_srcMR, r_srcAcc));
4342          return r_dst;
4343       }
4344    }
4345 
4346    if (e->tag == Iex_Triop) {
4347       IRTriop *triop = e->Iex.Triop.details;
4348       PPCFpOp fpop = Pfp_INVALID;
4349       switch (triop->op) {
4350          case Iop_AddF64:    fpop = Pfp_ADDD; break;
4351          case Iop_SubF64:    fpop = Pfp_SUBD; break;
4352          case Iop_MulF64:    fpop = Pfp_MULD; break;
4353          case Iop_DivF64:    fpop = Pfp_DIVD; break;
4354          case Iop_AddF64r32: fpop = Pfp_ADDS; break;
4355          case Iop_SubF64r32: fpop = Pfp_SUBS; break;
4356          case Iop_MulF64r32: fpop = Pfp_MULS; break;
4357          case Iop_DivF64r32: fpop = Pfp_DIVS; break;
4358          default: break;
4359       }
4360       if (fpop != Pfp_INVALID) {
4361          HReg r_dst  = newVRegF(env);
4362          HReg r_srcL = iselDblExpr(env, triop->arg2, IEndianess);
4363          HReg r_srcR = iselDblExpr(env, triop->arg3, IEndianess);
4364          set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4365          addInstr(env, PPCInstr_FpBinary(fpop, r_dst, r_srcL, r_srcR));
4366          return r_dst;
4367       }
4368    }
4369 
4370    if (e->tag == Iex_Binop) {
4371       PPCFpOp fpop = Pfp_INVALID;
4372       switch (e->Iex.Binop.op) {
4373       case Iop_SqrtF64:   fpop = Pfp_SQRT;   break;
4374       default: break;
4375       }
4376       if (fpop == Pfp_SQRT) {
4377          HReg fr_dst = newVRegF(env);
4378          HReg fr_src = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
4379          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4380          addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
4381          return fr_dst;
4382       }
4383    }
4384 
4385    if (e->tag == Iex_Binop) {
4386 
4387       if (e->Iex.Binop.op == Iop_F128toF64) {
4388          HReg fr_dst = newVRegF(env);
4389          HReg fr_src = iselFp128Expr(env, e->Iex.Binop.arg2, IEndianess);
4390          HReg tmp = newVRegV(env);
4391          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4392          PPCAMode* eight_r1 = PPCAMode_IR( 8, StackFramePtr(env->mode64) );
4393          PPCFpOp fpop = Pfp_INVALID;
4394 
4395          if (FPU_rounding_mode_isOdd(e->Iex.Binop.arg1)) {
4396             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4397             fpop = Pfp_FPQTODRNDODD;
4398          } else {
4399             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4400             fpop = Pfp_FPQTOD;
4401          }
4402 
4403          addInstr(env, PPCInstr_Fp128Unary(fpop, tmp, fr_src));
4404 
4405          /* result is in a 128-bit vector register, move to 64-bit reg to
4406           * match the Iop specification.  The result will get moved back
4407           * to a 128-bit register and stored once the value is returned.
4408           */
4409          sub_from_sp( env, 16 );
4410          addInstr(env, PPCInstr_AvLdSt(False/*store*/, 16, tmp, zero_r1));
4411          if (IEndianess == Iend_LE)
4412             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, eight_r1));
4413          else
4414             /* High 64-bits stored at lower address */
4415             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, zero_r1));
4416 
4417          add_to_sp( env, 16 );
4418 
4419          return fr_dst;
4420       }
4421 
4422       if (e->Iex.Binop.op == Iop_RoundF64toF32) {
4423          HReg r_dst = newVRegF(env);
4424          HReg r_src = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
4425          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4426          addInstr(env, PPCInstr_FpRSP(r_dst, r_src));
4427          //set_FPU_rounding_default( env );
4428          return r_dst;
4429       }
4430 
4431       if (e->Iex.Binop.op == Iop_I64StoF64 || e->Iex.Binop.op == Iop_I64UtoF64) {
4432          if (mode64) {
4433             HReg fdst = newVRegF(env);
4434             HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
4435             HReg r1   = StackFramePtr(env->mode64);
4436             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
4437 
4438             /* Set host rounding mode */
4439             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4440 
4441             sub_from_sp( env, 16 );
4442 
4443             addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
4444             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
4445             addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
4446                                           e->Iex.Binop.op == Iop_I64StoF64,
4447                                           True/*fdst is 64 bit*/,
4448                                           fdst, fdst));
4449 
4450             add_to_sp( env, 16 );
4451 
4452             ///* Restore default FPU rounding. */
4453             //set_FPU_rounding_default( env );
4454             return fdst;
4455          } else {
4456             /* 32-bit mode */
4457             HReg fdst = newVRegF(env);
4458             HReg isrcHi, isrcLo;
4459             HReg r1   = StackFramePtr(env->mode64);
4460             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
4461             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
4462 
4463             iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2,
4464                           IEndianess);
4465 
4466             /* Set host rounding mode */
4467             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4468 
4469             sub_from_sp( env, 16 );
4470 
4471             addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
4472             addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
4473             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
4474             addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
4475                                           e->Iex.Binop.op == Iop_I64StoF64,
4476                                           True/*fdst is 64 bit*/,
4477                                           fdst, fdst));
4478 
4479             add_to_sp( env, 16 );
4480 
4481             ///* Restore default FPU rounding. */
4482             //set_FPU_rounding_default( env );
4483             return fdst;
4484          }
4485       }
4486 
4487    }
4488 
4489    if (e->tag == Iex_Unop) {
4490       PPCFpOp fpop = Pfp_INVALID;
4491       switch (e->Iex.Unop.op) {
4492          case Iop_NegF64:     fpop = Pfp_NEG; break;
4493          case Iop_AbsF64:     fpop = Pfp_ABS; break;
4494          case Iop_RSqrtEst5GoodF64:      fpop = Pfp_RSQRTE; break;
4495          case Iop_RoundF64toF64_NegINF:  fpop = Pfp_FRIM; break;
4496          case Iop_RoundF64toF64_PosINF:  fpop = Pfp_FRIP; break;
4497          case Iop_RoundF64toF64_NEAREST: fpop = Pfp_FRIN; break;
4498          case Iop_RoundF64toF64_ZERO:    fpop = Pfp_FRIZ; break;
4499          default: break;
4500       }
4501       if (fpop != Pfp_INVALID) {
4502          HReg fr_dst = newVRegF(env);
4503          HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
4504          addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
4505          return fr_dst;
4506       }
4507    }
4508 
4509    if (e->tag == Iex_Unop) {
4510       switch (e->Iex.Unop.op) {
4511       case Iop_F128HItoF64:
4512       case Iop_F128LOtoF64:
4513          {
4514             /* put upper/lower 64-bits of F128 into an F64. */
4515             HReg     r_aligned16;
4516             HReg     fdst = newVRegF(env);
4517             HReg     fsrc = iselFp128Expr(env, e->Iex.Unop.arg, IEndianess);
4518             PPCAMode *am_off0, *am_off8, *am_off_arg;
4519             sub_from_sp( env, 32 );     // Move SP down 32 bytes
4520 
4521             // get a quadword aligned address within our stack space
4522             r_aligned16 = get_sp_aligned16( env );
4523             am_off0 = PPCAMode_IR( 0, r_aligned16 );
4524             am_off8 = PPCAMode_IR( 8 ,r_aligned16 );
4525 
4526             /* store 128-bit floating point value to memory, load low word
4527              * or high to 64-bit destination floating point register
4528              */
4529             addInstr(env, PPCInstr_AvLdSt(False/*store*/, 16, fsrc, am_off0));
4530             if (IEndianess == Iend_LE) {
4531                if (e->Iex.Binop.op == Iop_F128HItoF64)
4532                   am_off_arg = am_off8;
4533                else
4534                   am_off_arg = am_off0;
4535             } else {
4536                if (e->Iex.Binop.op == Iop_F128HItoF64)
4537                   am_off_arg = am_off0;
4538                else
4539                   am_off_arg = am_off8;
4540             }
4541             addInstr(env,
4542                     PPCInstr_FpLdSt( True /*load*/,
4543                                       8, fdst,
4544                                       am_off_arg ));
4545             add_to_sp( env, 32 );       // Reset SP
4546             return fdst;
4547          }
4548          case Iop_ReinterpI64asF64: {
4549             /* Given an I64, produce an IEEE754 double with the same
4550                bit pattern. */
4551             if (!mode64) {
4552                HReg r_srcHi, r_srcLo;
4553                iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg,
4554                                IEndianess);
4555                return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
4556             } else {
4557                HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
4558                return mk_LoadR64toFPR( env, r_src );
4559             }
4560          }
4561 
4562          case Iop_F32toF64: {
4563             if (e->Iex.Unop.arg->tag == Iex_Unop &&
4564                      e->Iex.Unop.arg->Iex.Unop.op == Iop_ReinterpI32asF32 ) {
4565                e = e->Iex.Unop.arg;
4566 
4567                HReg src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
4568                HReg fr_dst = newVRegF(env);
4569                PPCAMode *am_addr;
4570 
4571                sub_from_sp( env, 16 );        // Move SP down 16 bytes
4572                am_addr = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4573 
4574                // store src as Ity_I32's
4575                addInstr(env, PPCInstr_Store( 4, am_addr, src, env->mode64 ));
4576 
4577                // load single precision float, but the end results loads into a
4578                // 64-bit FP register -- i.e., F64.
4579                addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, fr_dst, am_addr));
4580 
4581                add_to_sp( env, 16 );          // Reset SP
4582                return fr_dst;
4583             }
4584 
4585 
4586             /* this is a no-op */
4587             HReg res = iselFltExpr(env, e->Iex.Unop.arg, IEndianess);
4588             return res;
4589          }
4590          default:
4591             break;
4592       }
4593    }
4594 
4595    /* --------- MULTIPLEX --------- */
4596    if (e->tag == Iex_ITE) { // VFD
4597       if (ty == Ity_F64
4598           && typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) {
4599          HReg fr1    = iselDblExpr(env, e->Iex.ITE.iftrue, IEndianess);
4600          HReg fr0    = iselDblExpr(env, e->Iex.ITE.iffalse, IEndianess);
4601          HReg fr_dst = newVRegF(env);
4602          addInstr(env, PPCInstr_FpUnary( Pfp_MOV, fr_dst, fr0 ));
4603          PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond, IEndianess);
4604          addInstr(env, PPCInstr_FpCMov( cc, fr_dst, fr1 ));
4605          return fr_dst;
4606       }
4607    }
4608 
4609    vex_printf("iselDblExpr(ppc): No such tag(%u)\n", e->tag);
4610    ppIRExpr(e);
4611    vpanic("iselDblExpr_wrk(ppc)");
4612 }
4613 
iselDfp32Expr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4614 static HReg iselDfp32Expr(ISelEnv* env, const IRExpr* e, IREndness IEndianess)
4615 {
4616    HReg r = iselDfp32Expr_wrk( env, e, IEndianess );
4617    vassert(hregClass(r) == HRcFlt64);
4618    vassert( hregIsVirtual(r) );
4619    return r;
4620 }
4621 
4622 /* DO NOT CALL THIS DIRECTLY */
iselDfp32Expr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4623 static HReg iselDfp32Expr_wrk(ISelEnv* env, const IRExpr* e,
4624                               IREndness IEndianess)
4625 {
4626    Bool mode64 = env->mode64;
4627    IRType ty = typeOfIRExpr( env->type_env, e );
4628 
4629    vassert( e );
4630    vassert( ty == Ity_D32 );
4631 
4632    /* --------- GET --------- */
4633    if (e->tag == Iex_Get) {
4634       HReg r_dst = newVRegF( env );
4635       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
4636                                        GuestStatePtr(mode64) );
4637       addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
4638       return r_dst;
4639    }
4640 
4641    /* --------- LOAD --------- */
4642    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
4643       PPCAMode* am_addr;
4644       HReg r_dst = newVRegF(env);
4645       vassert(e->Iex.Load.ty == Ity_D32);
4646       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D32/*xfer*/,
4647                                    IEndianess);
4648       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
4649       return r_dst;
4650    }
4651 
4652    /* --------- OPS --------- */
4653    if (e->tag == Iex_Binop) {
4654       if (e->Iex.Binop.op == Iop_D64toD32) {
4655          HReg fr_dst = newVRegF(env);
4656          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
4657          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4658          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DRSP, fr_dst, fr_src));
4659          return fr_dst;
4660       }
4661    }
4662 
4663    ppIRExpr( e );
4664    vpanic( "iselDfp32Expr_wrk(ppc)" );
4665 }
4666 
iselFp128Expr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4667 static HReg iselFp128Expr( ISelEnv* env, const IRExpr* e, IREndness IEndianess )
4668 {
4669    HReg r = iselFp128Expr_wrk( env, e, IEndianess );
4670    vassert(hregClass(r) == HRcVec128);
4671    vassert(hregIsVirtual(r));
4672    return r;
4673 }
4674 
4675 /* DO NOT CALL THIS DIRECTLY */
iselFp128Expr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4676 static HReg iselFp128Expr_wrk( ISelEnv* env, const IRExpr* e,
4677                                IREndness IEndianess)
4678 {
4679    Bool mode64 = env->mode64;
4680    PPCFpOp fpop = Pfp_INVALID;
4681    IRType  ty = typeOfIRExpr(env->type_env,e);
4682 
4683    vassert(e);
4684    vassert( ty == Ity_F128 );
4685 
4686    /* read 128-bit IRTemp */
4687    if (e->tag == Iex_RdTmp) {
4688       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
4689    }
4690 
4691   if (e->tag == Iex_Get) {
4692       /* Guest state vectors are 16byte aligned,
4693          so don't need to worry here */
4694       HReg dst = newVRegV(env);
4695 
4696       addInstr(env,
4697                PPCInstr_AvLdSt( True/*load*/, 16, dst,
4698                                 PPCAMode_IR( e->Iex.Get.offset,
4699                                              GuestStatePtr(mode64) )));
4700       return dst;
4701    }
4702 
4703    if (e->tag == Iex_Unop) {
4704       switch (e->Iex.Unop.op) {
4705       case Iop_TruncF128toI64S:
4706          fpop = Pfp_TRUNCFPQTOISD; goto do_Un_F128;
4707       case Iop_TruncF128toI32S:
4708          fpop = Pfp_TRUNCFPQTOISW; goto do_Un_F128;
4709       case Iop_TruncF128toI64U:
4710          fpop = Pfp_TRUNCFPQTOIUD; goto do_Un_F128;
4711       case Iop_TruncF128toI32U:
4712          fpop = Pfp_TRUNCFPQTOIUW; goto do_Un_F128;
4713 
4714       do_Un_F128: {
4715          HReg r_dst = newVRegV(env);
4716          HReg r_src = iselFp128Expr(env, e->Iex.Unop.arg, IEndianess);
4717          addInstr(env, PPCInstr_Fp128Unary(fpop, r_dst, r_src));
4718          return r_dst;
4719       }
4720 
4721       case Iop_F64toF128: {
4722          fpop = Pfp_FPDTOQ;
4723          HReg r_dst = newVRegV(env);
4724          HReg r_src = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
4725          HReg v128tmp = newVRegV(env);
4726          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4727 
4728          /* value is in 64-bit float reg, need to move to 128-bit vector reg */
4729          sub_from_sp( env, 16 );
4730          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, r_src, zero_r1));
4731          addInstr(env, PPCInstr_AvLdSt(True/*load*/, 16, v128tmp, zero_r1));
4732          add_to_sp( env, 16 );
4733 
4734          addInstr(env, PPCInstr_Fp128Unary(fpop, r_dst, v128tmp));
4735          return r_dst;
4736       }
4737 
4738       case Iop_I64StoF128:
4739          fpop = Pfp_IDSTOQ; goto do_Un_int_F128;
4740       case Iop_I64UtoF128:
4741          fpop = Pfp_IDUTOQ; goto do_Un_int_F128;
4742 
4743       do_Un_int_F128: {
4744          HReg r_dst = newVRegV(env);
4745          HReg tmp = newVRegV(env);
4746          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
4747          PPCAMode *am_offhi, *am_offlo;
4748          HReg r_aligned16;
4749 
4750          /* source is in a 64-bit integer reg, move to 128-bit float reg
4751           * do this via the stack (easy, convenient, etc).
4752           */
4753          sub_from_sp( env, 32 );        // Move SP down
4754 
4755          /* Get a quadword aligned address within our stack space */
4756          r_aligned16 = get_sp_aligned16( env );
4757 
4758          am_offlo  = PPCAMode_IR( 0,  r_aligned16 );
4759          am_offhi  = PPCAMode_IR( 8,  r_aligned16 );
4760 
4761          /* Inst only uses the upper 64-bit of the source */
4762          addInstr(env, PPCInstr_Load(8, r_src, am_offhi, mode64));
4763 
4764          /* Fetch result back from stack. */
4765          addInstr(env, PPCInstr_AvLdSt(True/*load*/, 16, tmp, am_offlo));
4766 
4767          add_to_sp( env, 32 );          // Reset SP
4768 
4769          addInstr(env, PPCInstr_Fp128Unary(fpop, r_dst, tmp));
4770          return r_dst;
4771       }
4772 
4773       default:
4774          break;
4775       } /* switch (e->Iex.Unop.op) */
4776    } /* if (e->tag == Iex_Unop) */
4777 
4778    if (e->tag == Iex_Binop) {
4779       switch (e->Iex.Binop.op) {
4780 
4781       case Iop_F64HLtoF128:
4782          {
4783             HReg dst    = newVRegV(env);
4784             HReg r_src_hi = iselDblExpr(env, e->Iex.Binop.arg1, IEndianess);
4785             HReg r_src_lo = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
4786             PPCAMode *am_offhi, *am_offlo;
4787             HReg r_aligned16;
4788 
4789             /* do this via the stack (easy, convenient, etc) */
4790             sub_from_sp( env, 16 );        // Move SP down
4791 
4792             /* Get a quadword aligned address within our stack space */
4793             r_aligned16 = get_sp_aligned16( env );
4794 
4795             am_offlo  = PPCAMode_IR( 0,  r_aligned16 );
4796             am_offhi  = PPCAMode_IR( 8,  r_aligned16 );
4797 
4798             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8,
4799                                           r_src_lo, am_offlo));
4800             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8,
4801                                           r_src_hi, am_offhi));
4802 
4803             /* Fetch result back from stack. */
4804             addInstr(env, PPCInstr_AvLdSt(True/*load*/, 16,
4805                                           dst, am_offlo));
4806 
4807             add_to_sp( env, 16 );          // Reset SP
4808             return dst;
4809          }
4810       case Iop_F128toI128S:
4811          {
4812             HReg dst    = newVRegV(env);
4813             HReg r_src  = iselFp128Expr(env, e->Iex.Binop.arg2, IEndianess);
4814             PPCRI* rm = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
4815             /* Note: rm is a set of three bit fields that specify the
4816              * rounding mode and which of the two instructions to issue.
4817              */
4818             addInstr(env, PPCInstr_AvBinaryInt(Pav_F128toI128S, dst,
4819                                                r_src, rm));
4820             return dst;
4821          }
4822       case Iop_RndF128:
4823          {
4824             HReg dst    = newVRegV(env);
4825             HReg r_src  = iselFp128Expr(env, e->Iex.Binop.arg2, IEndianess);
4826             PPCRI* rm = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
4827             /* Note: rm is a set of three bit fields that specify the
4828              * rounding mode and which of the two instructions to issue.
4829              */
4830             addInstr(env, PPCInstr_AvBinaryInt(Pav_ROUNDFPQ, dst,
4831                                                r_src, rm));
4832             return dst;
4833          }
4834       case Iop_SqrtF128:
4835          if (FPU_rounding_mode_isOdd(e->Iex.Binop.arg1)) {
4836             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4837             fpop = Pfp_FPSQRTQRNDODD;
4838             goto do_Bin_F128;
4839          } else {
4840             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4841             fpop = Pfp_FPSQRTQ;
4842             goto do_Bin_F128;
4843          }
4844       case Iop_F128toF32:
4845          if (FPU_rounding_mode_isOdd(e->Iex.Binop.arg1)) {
4846             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4847             fpop = Pfp_FPQTOWRNDODD;
4848             goto do_Bin_F128;
4849          } else {
4850             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4851             fpop = Pfp_FPQTOW;
4852             goto do_Bin_F128;
4853          }
4854       do_Bin_F128: {
4855          HReg r_dst = newVRegV(env);
4856          HReg r_src = iselFp128Expr(env, e->Iex.Binop.arg2, IEndianess);
4857          addInstr(env, PPCInstr_Fp128Unary(fpop, r_dst, r_src));
4858          return r_dst;
4859       }
4860 
4861       default:
4862          break;
4863       } /* switch (e->Iex.Binop.op) */
4864    } /* if (e->tag == Iex_Binop) */
4865 
4866    if (e->tag == Iex_Triop) {
4867       IRTriop *triop = e->Iex.Triop.details;
4868 
4869       switch (triop->op) {
4870       case Iop_AddF128:
4871          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4872             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4873             fpop = Pfp_FPADDQRNDODD; goto do_Tri_F128;
4874          } else {
4875             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4876             fpop = Pfp_FPADDQ; goto do_Tri_F128;
4877          }
4878       case Iop_SubF128:
4879          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4880             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4881             fpop = Pfp_FPSUBQRNDODD; goto do_Tri_F128;
4882          } else {
4883             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4884             fpop = Pfp_FPSUBQ; goto do_Tri_F128;
4885          }
4886       case Iop_MulF128:
4887          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4888             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4889             fpop = Pfp_FPMULQRNDODD; goto do_Tri_F128;
4890          } else {
4891             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4892             fpop = Pfp_FPMULQ; goto do_Tri_F128;
4893          }
4894       case Iop_DivF128:
4895          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4896             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4897             fpop = Pfp_FPDIVQRNDODD; goto do_Tri_F128;
4898          } else {
4899             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4900             fpop = Pfp_FPDIVQ; goto do_Tri_F128;
4901          }
4902       case Iop_MAddF128:
4903          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4904             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4905             fpop = Pfp_FPMULADDQRNDODD; goto do_Tri_F128;
4906          } else {
4907             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4908             fpop = Pfp_FPMULADDQ; goto do_Tri_F128;
4909          }
4910 
4911    do_Tri_F128: {
4912          HReg r_dst  = newVRegV(env);
4913          HReg r_srcL = iselFp128Expr(env, triop->arg2, IEndianess);
4914          HReg r_srcR = iselFp128Expr(env, triop->arg3, IEndianess);
4915 
4916          addInstr(env, PPCInstr_Fp128Binary(fpop, r_dst, r_srcL, r_srcR));
4917          return r_dst;
4918       }
4919 
4920       default:
4921          break;
4922       } /* switch (e->Iex.Triop.op) */
4923 
4924    } /* if (e->tag == Iex_Trinop) */
4925 
4926    if (e->tag == Iex_Qop) {
4927       IRQop *qop = e->Iex.Qop.details;
4928 
4929       switch (qop->op) {
4930       case Iop_MAddF128:
4931          if (FPU_rounding_mode_isOdd(qop->arg1)) {
4932             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4933             fpop = Pfp_FPMULADDQRNDODD; goto do_Quad_F128;
4934          } else {
4935             set_FPU_rounding_mode( env, qop->arg1, IEndianess );
4936             fpop = Pfp_FPMULADDQ; goto do_Quad_F128;
4937          }
4938       case Iop_MSubF128:
4939          if (FPU_rounding_mode_isOdd(qop->arg1)) {
4940             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4941             fpop = Pfp_FPMULSUBQRNDODD; goto do_Quad_F128;
4942          } else {
4943             set_FPU_rounding_mode( env, qop->arg1, IEndianess );
4944             fpop = Pfp_FPMULSUBQ; goto do_Quad_F128;
4945          }
4946       case Iop_NegMAddF128:
4947          if (FPU_rounding_mode_isOdd(qop->arg1)) {
4948             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4949             fpop = Pfp_FPNEGMULADDQRNDODD; goto do_Quad_F128;
4950          } else {
4951             set_FPU_rounding_mode( env, qop->arg1, IEndianess );
4952             fpop = Pfp_FPNEGMULADDQ; goto do_Quad_F128;
4953          }
4954       case Iop_NegMSubF128:
4955          if (FPU_rounding_mode_isOdd(qop->arg1)) {
4956             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4957             fpop = Pfp_FPNEGMULSUBQRNDODD; goto do_Quad_F128;
4958          } else {
4959             set_FPU_rounding_mode( env, qop->arg1, IEndianess );
4960             fpop = Pfp_FPNEGMULSUBQ; goto do_Quad_F128;
4961          }
4962 
4963       do_Quad_F128: {
4964          HReg r_dst = iselFp128Expr(env, qop->arg3,
4965                                     IEndianess);
4966          HReg r_srcL = iselFp128Expr(env, qop->arg2,
4967                                      IEndianess);
4968          HReg r_srcR = iselFp128Expr(env, qop->arg4,
4969                                      IEndianess);
4970 
4971          addInstr(env, PPCInstr_Fp128Trinary(fpop, r_dst, r_srcL, r_srcR));
4972          return r_dst;
4973          }
4974 
4975       default:
4976          break;
4977       }
4978    }   /* if (e->tag == Iex_Qop) */
4979 
4980    ppIRExpr( e );
4981    vpanic( "iselFp128Expr(ppc64)" );
4982 }
4983 
iselDfp64Expr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4984 static HReg iselDfp64Expr(ISelEnv* env, const IRExpr* e, IREndness IEndianess)
4985 {
4986    HReg r = iselDfp64Expr_wrk( env, e, IEndianess );
4987    vassert(hregClass(r) == HRcFlt64);
4988    vassert( hregIsVirtual(r) );
4989    return r;
4990 }
4991 
4992 /* DO NOT CALL THIS DIRECTLY */
iselDfp64Expr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4993 static HReg iselDfp64Expr_wrk(ISelEnv* env, const IRExpr* e,
4994                               IREndness IEndianess)
4995 {
4996    Bool mode64 = env->mode64;
4997    IRType ty = typeOfIRExpr( env->type_env, e );
4998    HReg r_dstHi, r_dstLo;
4999 
5000    vassert( e );
5001    vassert( ty == Ity_D64 );
5002 
5003    if (e->tag == Iex_RdTmp) {
5004       return lookupIRTemp( env, e->Iex.RdTmp.tmp );
5005    }
5006 
5007    /* --------- GET --------- */
5008    if (e->tag == Iex_Get) {
5009       HReg r_dst = newVRegF( env );
5010       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
5011                                        GuestStatePtr(mode64) );
5012       addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
5013       return r_dst;
5014    }
5015 
5016    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
5017       PPCAMode* am_addr;
5018       HReg r_dst = newVRegF(env);
5019       vassert(e->Iex.Load.ty == Ity_D64);
5020       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D64/*xfer*/,
5021                                    IEndianess);
5022       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
5023       return r_dst;
5024    }
5025 
5026    /* --------- OPS --------- */
5027    if (e->tag == Iex_Qop) {
5028       HReg r_dst = newVRegF( env );
5029       return r_dst;
5030    }
5031 
5032    if (e->tag == Iex_Unop) {
5033       HReg fr_dst = newVRegF(env);
5034       switch (e->Iex.Unop.op) {
5035       case Iop_ReinterpI64asD64: {
5036          /* Given an I64, produce an IEEE754 DFP with the same
5037                bit pattern. */
5038          if (!mode64) {
5039             HReg r_srcHi, r_srcLo;
5040             iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg,
5041                            IEndianess);
5042             return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
5043          } else {
5044             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
5045             return mk_LoadR64toFPR( env, r_src );
5046          }
5047       }
5048       case Iop_D32toD64: {
5049          HReg fr_src = iselDfp32Expr(env, e->Iex.Unop.arg, IEndianess);
5050          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
5051          return fr_dst;
5052       }
5053       case Iop_D128HItoD64:
5054          iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg,
5055                          IEndianess );
5056          return r_dstHi;
5057       case Iop_D128LOtoD64:
5058          iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg,
5059                          IEndianess );
5060          return r_dstLo;
5061       case Iop_InsertExpD64: {
5062          HReg fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1, IEndianess);
5063          HReg fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
5064 
5065          addInstr(env, PPCInstr_Dfp64Binary(Pfp_DIEX, fr_dst, fr_srcL,
5066 					    fr_srcR));
5067          return fr_dst;
5068        }
5069       default:
5070          vex_printf( "ERROR: iselDfp64Expr_wrk, UNKNOWN unop case %d\n",
5071                      (Int)e->Iex.Unop.op );
5072       }
5073    }
5074 
5075    if (e->tag == Iex_Binop) {
5076       PPCFpOp fpop = Pfp_INVALID;
5077       HReg fr_dst = newVRegF(env);
5078 
5079       switch (e->Iex.Binop.op) {
5080       case Iop_D128toD64:     fpop = Pfp_DRDPQ;  break;
5081       case Iop_D64toD32:      fpop = Pfp_DRSP;   break;
5082       case Iop_I64StoD64:     fpop = Pfp_DCFFIX; break;
5083       case Iop_RoundD64toInt: fpop = Pfp_DRINTN; break;
5084       default: break;
5085       }
5086       if (fpop == Pfp_DRDPQ) {
5087          HReg r_srcHi = newVRegF(env);
5088          HReg r_srcLo = newVRegF(env);
5089 
5090          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
5091          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
5092                         IEndianess);
5093          addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
5094          return fr_dst;
5095 
5096       } else if (fpop == Pfp_DRINTN) {
5097          HReg fr_src = newVRegF(env);
5098          PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
5099 
5100          /* NOTE, this IOP takes a DFP value and rounds to the
5101           * neares floating point integer value, i.e. fractional part
5102           * is zero.  The result is a decimal floating point number.
5103           * the INT in the name is a bit misleading.
5104           */
5105          fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
5106          addInstr(env, PPCInstr_DfpRound(fr_dst, fr_src, r_rmc));
5107          return fr_dst;
5108 
5109       } else if (fpop == Pfp_DRSP) {
5110          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
5111          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
5112          addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
5113          return fr_dst;
5114 
5115       } else if (fpop == Pfp_DCFFIX) {
5116          HReg fr_src = newVRegF(env);
5117          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5118 
5119          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
5120          sub_from_sp( env, 16 );
5121 
5122          // put the I64 value into a floating point register
5123          if (mode64) {
5124            HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
5125 
5126            addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
5127          } else {
5128             HReg tmpHi, tmpLo;
5129             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
5130 
5131             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Binop.arg2,
5132                           IEndianess);
5133             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
5134             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
5135          }
5136 
5137          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8,  fr_src, zero_r1));
5138          addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
5139          add_to_sp( env, 16 );
5140          return fr_dst;
5141       }
5142 
5143       switch (e->Iex.Binop.op) {
5144       /* shift instructions D64, I32 -> D64 */
5145       case Iop_ShlD64: fpop = Pfp_DSCLI; break;
5146       case Iop_ShrD64: fpop = Pfp_DSCRI; break;
5147       default: break;
5148       }
5149       if (fpop != Pfp_INVALID) {
5150          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg1, IEndianess);
5151          PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
5152 
5153          /* shift value must be an immediate value */
5154          vassert(shift->tag == Pri_Imm);
5155 
5156          addInstr(env, PPCInstr_DfpShift(fpop, fr_dst, fr_src, shift));
5157          return fr_dst;
5158       }
5159 
5160       switch (e->Iex.Binop.op) {
5161       case Iop_InsertExpD64:
5162          fpop = Pfp_DIEX;
5163          break;
5164       default: 	break;
5165       }
5166       if (fpop != Pfp_INVALID) {
5167          HReg fr_srcL = newVRegF(env);
5168          HReg fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
5169          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5170          sub_from_sp( env, 16 );
5171 
5172          if (env->mode64) {
5173             // put the I64 value into a floating point reg
5174             HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
5175 
5176             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
5177          } else {
5178             // put the I64 register pair into a floating point reg
5179             HReg tmpHi;
5180             HReg tmpLo;
5181             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
5182 
5183             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Binop.arg1,
5184                           IEndianess);
5185             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*!mode64*/));
5186             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*!mode64*/));
5187          }
5188          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_srcL, zero_r1));
5189          addInstr(env, PPCInstr_Dfp64Binary(fpop, fr_dst, fr_srcL,
5190                                             fr_srcR));
5191          add_to_sp( env, 16 );
5192          return fr_dst;
5193       }
5194    }
5195 
5196    if (e->tag == Iex_Triop) {
5197       IRTriop *triop = e->Iex.Triop.details;
5198       PPCFpOp fpop = Pfp_INVALID;
5199 
5200       switch (triop->op) {
5201       case Iop_AddD64:
5202          fpop = Pfp_DFPADD;
5203          break;
5204       case Iop_SubD64:
5205          fpop = Pfp_DFPSUB;
5206          break;
5207       case Iop_MulD64:
5208          fpop = Pfp_DFPMUL;
5209          break;
5210       case Iop_DivD64:
5211          fpop = Pfp_DFPDIV;
5212          break;
5213       default:
5214          break;
5215       }
5216       if (fpop != Pfp_INVALID) {
5217          HReg r_dst = newVRegF( env );
5218          HReg r_srcL = iselDfp64Expr( env, triop->arg2, IEndianess );
5219          HReg r_srcR = iselDfp64Expr( env, triop->arg3, IEndianess );
5220 
5221          set_FPU_DFP_rounding_mode( env, triop->arg1, IEndianess );
5222          addInstr( env, PPCInstr_Dfp64Binary( fpop, r_dst, r_srcL, r_srcR ) );
5223          return r_dst;
5224       }
5225 
5226       switch (triop->op) {
5227       case Iop_QuantizeD64:          fpop = Pfp_DQUA;  break;
5228       case Iop_SignificanceRoundD64: fpop = Pfp_RRDTR; break;
5229       default: break;
5230       }
5231       if (fpop == Pfp_DQUA) {
5232          HReg r_dst = newVRegF(env);
5233          HReg r_srcL = iselDfp64Expr(env, triop->arg2, IEndianess);
5234          HReg r_srcR = iselDfp64Expr(env, triop->arg3, IEndianess);
5235          PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1, IEndianess);
5236          addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR,
5237                                             rmc));
5238          return r_dst;
5239 
5240       } else if (fpop == Pfp_RRDTR) {
5241          HReg r_dst = newVRegF(env);
5242          HReg r_srcL = newVRegF(env);
5243          HReg r_srcR = iselDfp64Expr(env, triop->arg3, IEndianess);
5244          PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1, IEndianess);
5245          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5246          HReg i8_val = iselWordExpr_R(env, triop->arg2, IEndianess);
5247 
5248          /* Move I8 to float register to issue instruction */
5249          sub_from_sp( env, 16 );
5250          if (mode64)
5251             addInstr(env, PPCInstr_Store(8, zero_r1, i8_val, True/*mode64*/));
5252          else
5253             addInstr(env, PPCInstr_Store(4, zero_r1, i8_val, False/*mode32*/));
5254 
5255          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_srcL, zero_r1));
5256          add_to_sp( env, 16 );
5257 
5258          // will set TE and RMC when issuing instruction
5259          addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR, rmc));
5260          return r_dst;
5261       }
5262    }
5263 
5264    ppIRExpr( e );
5265    vpanic( "iselDfp64Expr_wrk(ppc)" );
5266 }
5267 
iselDfp128Expr(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)5268 static void iselDfp128Expr(HReg* rHi, HReg* rLo, ISelEnv* env, const IRExpr* e,
5269                            IREndness IEndianess)
5270 {
5271    iselDfp128Expr_wrk( rHi, rLo, env, e, IEndianess );
5272    vassert( hregIsVirtual(*rHi) );
5273    vassert( hregIsVirtual(*rLo) );
5274 }
5275 
5276 /* DO NOT CALL THIS DIRECTLY */
iselDfp128Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)5277 static void iselDfp128Expr_wrk(HReg* rHi, HReg *rLo, ISelEnv* env,
5278                                const IRExpr* e, IREndness IEndianess)
5279 {
5280    vassert( e );
5281    vassert( typeOfIRExpr(env->type_env,e) == Ity_D128 );
5282 
5283    /* read 128-bit IRTemp */
5284    if (e->tag == Iex_RdTmp) {
5285       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp );
5286       return;
5287    }
5288 
5289    if (e->tag == Iex_Unop) {
5290       HReg r_dstHi = newVRegF(env);
5291       HReg r_dstLo = newVRegF(env);
5292 
5293       if (e->Iex.Unop.op == Iop_I64StoD128) {
5294          HReg fr_src = newVRegF(env);
5295          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5296 
5297          // put the I64 value into a floating point reg
5298          if (env->mode64) {
5299             HReg tmp   = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
5300             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
5301          } else {
5302             HReg tmpHi, tmpLo;
5303             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
5304 
5305             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg,
5306                           IEndianess);
5307             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
5308             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
5309          }
5310 
5311          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_src, zero_r1));
5312          addInstr(env, PPCInstr_DfpI64StoD128(Pfp_DCFFIXQ, r_dstHi, r_dstLo,
5313                                               fr_src));
5314       }
5315 
5316       if (e->Iex.Unop.op == Iop_D64toD128) {
5317          HReg r_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
5318 
5319          /* Source is 64bit, result is 128 bit.  High 64bit source arg,
5320           * is ignored by the instruction.  Set high arg to r_src just
5321           * to meet the vassert tests.
5322           */
5323          addInstr(env, PPCInstr_Dfp128Unary(Pfp_DCTQPQ, r_dstHi, r_dstLo,
5324                                             r_src, r_src));
5325       }
5326       *rHi = r_dstHi;
5327       *rLo = r_dstLo;
5328       return;
5329    }
5330 
5331    /* --------- OPS --------- */
5332    if (e->tag == Iex_Binop) {
5333       HReg r_srcHi;
5334       HReg r_srcLo;
5335 
5336       switch (e->Iex.Binop.op) {
5337       case Iop_D64HLtoD128:
5338          r_srcHi = iselDfp64Expr( env, e->Iex.Binop.arg1, IEndianess );
5339          r_srcLo = iselDfp64Expr( env, e->Iex.Binop.arg2, IEndianess );
5340          *rHi = r_srcHi;
5341          *rLo = r_srcLo;
5342          return;
5343          break;
5344       case Iop_D128toD64: {
5345          PPCFpOp fpop = Pfp_DRDPQ;
5346          HReg fr_dst  = newVRegF(env);
5347 
5348          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
5349          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
5350                         IEndianess);
5351          addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
5352 
5353          /* Need to meet the interface spec but the result is
5354           * just 64-bits so send the result back in both halfs.
5355           */
5356          *rHi = fr_dst;
5357          *rLo = fr_dst;
5358          return;
5359       }
5360       case Iop_ShlD128:
5361       case Iop_ShrD128: {
5362          HReg fr_dst_hi = newVRegF(env);
5363          HReg fr_dst_lo = newVRegF(env);
5364          PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
5365          PPCFpOp fpop = Pfp_DSCLIQ;  /* fix later if necessary */
5366 
5367          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1,
5368                         IEndianess);
5369 
5370          if (e->Iex.Binop.op == Iop_ShrD128)
5371             fpop = Pfp_DSCRIQ;
5372 
5373          addInstr(env, PPCInstr_DfpShift128(fpop, fr_dst_hi, fr_dst_lo,
5374                                             r_srcHi, r_srcLo, shift));
5375 
5376          *rHi = fr_dst_hi;
5377          *rLo = fr_dst_lo;
5378          return;
5379       }
5380       case Iop_RoundD128toInt: {
5381          HReg r_dstHi = newVRegF(env);
5382          HReg r_dstLo = newVRegF(env);
5383          PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
5384 
5385          // will set R and RMC when issuing instruction
5386          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
5387                         IEndianess);
5388 
5389          addInstr(env, PPCInstr_DfpRound128(r_dstHi, r_dstLo,
5390                                             r_srcHi, r_srcLo, r_rmc));
5391          *rHi = r_dstHi;
5392          *rLo = r_dstLo;
5393          return;
5394       }
5395       case Iop_InsertExpD128: {
5396          HReg r_dstHi = newVRegF(env);
5397          HReg r_dstLo = newVRegF(env);
5398          HReg r_srcL  = newVRegF(env);
5399          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5400          r_srcHi = newVRegF(env);
5401          r_srcLo = newVRegF(env);
5402 
5403          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
5404                         IEndianess);
5405 
5406          /* Move I64 to float register to issue instruction */
5407          if (env->mode64) {
5408             HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
5409             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
5410          } else {
5411             HReg tmpHi, tmpLo;
5412             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
5413 
5414             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg,
5415                           IEndianess);
5416             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
5417             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
5418          }
5419 
5420          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_srcL, zero_r1));
5421          addInstr(env, PPCInstr_InsertExpD128(Pfp_DIEXQ,
5422                                               r_dstHi, r_dstLo,
5423                                               r_srcL, r_srcHi, r_srcLo));
5424          *rHi = r_dstHi;
5425          *rLo = r_dstLo;
5426          return;
5427       }
5428       default:
5429          vex_printf( "ERROR: iselDfp128Expr_wrk, UNKNOWN binop case %d\n",
5430                      (Int)e->Iex.Binop.op );
5431          break;
5432       }
5433    }
5434 
5435    if (e->tag == Iex_Triop) {
5436       IRTriop *triop = e->Iex.Triop.details;
5437       PPCFpOp fpop = Pfp_INVALID;
5438       HReg r_dstHi = newVRegF(env);
5439       HReg r_dstLo = newVRegF(env);
5440 
5441       switch (triop->op) {
5442       case Iop_AddD128:
5443          fpop = Pfp_DFPADDQ;
5444          break;
5445       case Iop_SubD128:
5446          fpop = Pfp_DFPSUBQ;
5447          break;
5448       case Iop_MulD128:
5449          fpop = Pfp_DFPMULQ;
5450          break;
5451       case Iop_DivD128:
5452          fpop = Pfp_DFPDIVQ;
5453          break;
5454       default:
5455          break;
5456       }
5457 
5458       if (fpop != Pfp_INVALID) {
5459          HReg r_srcRHi = newVRegV( env );
5460          HReg r_srcRLo = newVRegV( env );
5461 
5462          /* dst will be used to pass in the left operand and get the result. */
5463          iselDfp128Expr( &r_dstHi, &r_dstLo, env, triop->arg2, IEndianess );
5464          iselDfp128Expr( &r_srcRHi, &r_srcRLo, env, triop->arg3, IEndianess );
5465          set_FPU_DFP_rounding_mode( env, triop->arg1, IEndianess );
5466          addInstr( env,
5467                    PPCInstr_Dfp128Binary( fpop, r_dstHi, r_dstLo,
5468                                           r_srcRHi, r_srcRLo ) );
5469          *rHi = r_dstHi;
5470          *rLo = r_dstLo;
5471          return;
5472       }
5473       switch (triop->op) {
5474       case Iop_QuantizeD128:          fpop = Pfp_DQUAQ;  break;
5475       case Iop_SignificanceRoundD128: fpop = Pfp_DRRNDQ; break;
5476       default: break;
5477       }
5478       if (fpop == Pfp_DQUAQ) {
5479          HReg r_srcHi = newVRegF(env);
5480          HReg r_srcLo = newVRegF(env);
5481          PPCRI* rmc = iselWordExpr_RI(env, triop->arg1, IEndianess);
5482 
5483          /* dst will be used to pass in the left operand and get the result */
5484          iselDfp128Expr(&r_dstHi, &r_dstLo, env, triop->arg2, IEndianess);
5485          iselDfp128Expr(&r_srcHi, &r_srcLo, env, triop->arg3, IEndianess);
5486 
5487          // will set RMC when issuing instruction
5488          addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
5489                                                r_srcHi, r_srcLo, rmc));
5490         *rHi = r_dstHi;
5491         *rLo = r_dstLo;
5492          return;
5493 
5494       } else if (fpop == Pfp_DRRNDQ) {
5495          HReg r_srcHi = newVRegF(env);
5496          HReg r_srcLo = newVRegF(env);
5497          PPCRI* rmc = iselWordExpr_RI(env, triop->arg1, IEndianess);
5498          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5499          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
5500          HReg i8_val = iselWordExpr_R(env, triop->arg2, IEndianess);
5501          HReg r_zero = newVRegI( env );
5502 
5503          iselDfp128Expr(&r_srcHi, &r_srcLo, env, triop->arg3, IEndianess);
5504 
5505          /* dst will be used to pass in the left operand and get the result */
5506          /* Move I8 to float register to issue instruction.  Note, the
5507           * instruction only looks at the bottom 6 bits so we really don't
5508           * have to clear the upper bits since the iselWordExpr_R sets the
5509           * bottom 8-bits.
5510           */
5511          sub_from_sp( env, 16 );
5512 
5513          if (env->mode64)
5514             addInstr(env, PPCInstr_Store(4, four_r1, i8_val, True/*mode64*/));
5515          else
5516             addInstr(env, PPCInstr_Store(4, four_r1, i8_val, False/*mode32*/));
5517 
5518          /* Have to write to the upper bits to ensure they have been
5519           * initialized. The instruction ignores all but the lower 6-bits.
5520           */
5521          addInstr( env, PPCInstr_LI( r_zero, 0, env->mode64 ) );
5522          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dstHi, zero_r1));
5523          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dstLo, zero_r1));
5524 
5525          add_to_sp( env, 16 );
5526 
5527          // will set RMC when issuing instruction
5528          addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
5529                                                r_srcHi, r_srcLo, rmc));
5530          *rHi = r_dstHi;
5531          *rLo = r_dstLo;
5532          return;
5533       }
5534  }
5535 
5536    ppIRExpr( e );
5537    vpanic( "iselDfp128Expr(ppc64)" );
5538 }
5539 
5540 
5541 /*---------------------------------------------------------*/
5542 /*--- ISEL: SIMD (Vector) expressions, 128 bit.         ---*/
5543 /*---------------------------------------------------------*/
5544 
iselVecExpr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)5545 static HReg iselVecExpr ( ISelEnv* env, const IRExpr* e, IREndness IEndianess )
5546 {
5547    HReg r = iselVecExpr_wrk( env, e, IEndianess );
5548 #  if 0
5549    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
5550 #  endif
5551    vassert(hregClass(r) == HRcVec128);
5552    vassert(hregIsVirtual(r));
5553    return r;
5554 }
5555 
5556 /* DO NOT CALL THIS DIRECTLY */
iselVecExpr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)5557 static HReg iselVecExpr_wrk ( ISelEnv* env, const IRExpr* e,
5558                               IREndness IEndianess )
5559 {
5560    Bool mode64 = env->mode64;
5561    PPCAvOp op = Pav_INVALID;
5562    PPCAvFpOp fpop = Pavfp_INVALID;
5563    IRType  ty = typeOfIRExpr(env->type_env,e);
5564    vassert(e);
5565    vassert(ty == Ity_V128);
5566 
5567    if (e->tag == Iex_RdTmp) {
5568       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
5569    }
5570 
5571    if (e->tag == Iex_Get) {
5572       /* Guest state vectors are 16byte aligned,
5573          so don't need to worry here */
5574       HReg dst = newVRegV(env);
5575       addInstr(env,
5576                PPCInstr_AvLdSt( True/*load*/, 16, dst,
5577                                 PPCAMode_IR( e->Iex.Get.offset,
5578                                              GuestStatePtr(mode64) )));
5579       return dst;
5580    }
5581 
5582    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
5583       /* Need to be able to do V128 unaligned loads. The BE unaligned load
5584        * can be accomplised using the following code sequece from the ISA.
5585        * It uses the lvx instruction that does two aligned loads and then
5586        * permute the data to store the required data as if it had been an
5587        * unaligned load.
5588        *
5589        *   lvx  Vhi,0,Rb        # load MSQ, using the unaligned address in Rb
5590        *   lvsl Vp, 0,Rb        # Set permute control vector
5591        *   addi Rb,Rb,15        # Address of LSQ
5592        *   lvx  Vlo,0,Rb        # load LSQ
5593        *   vperm Vt,Vhi,Vlo,Vp  # align the data as requested
5594        */
5595 
5596       HReg Vhi   = newVRegV(env);
5597       HReg Vlo   = newVRegV(env);
5598       HReg Vp    = newVRegV(env);
5599       HReg v_dst = newVRegV(env);
5600       HReg rB;
5601       HReg rB_plus_15 = newVRegI(env);
5602 
5603       vassert(e->Iex.Load.ty == Ity_V128);
5604       rB = iselWordExpr_R( env, e->Iex.Load.addr, IEndianess );
5605 
5606       // lvx  Vhi, 0, Rb
5607       addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, Vhi,
5608                                      PPCAMode_IR(0, rB)) );
5609 
5610       if (IEndianess == Iend_LE)
5611          // lvsr Vp, 0, Rb
5612          addInstr(env, PPCInstr_AvSh( False/*right shift*/, Vp,
5613                                       PPCAMode_IR(0, rB)) );
5614       else
5615          // lvsl Vp, 0, Rb
5616          addInstr(env, PPCInstr_AvSh( True/*left shift*/, Vp,
5617                                       PPCAMode_IR(0, rB)) );
5618 
5619       // addi Rb_plus_15, Rb, 15
5620       addInstr(env, PPCInstr_Alu( Palu_ADD, rB_plus_15,
5621                                   rB, PPCRH_Imm(True, toUShort(15))) );
5622 
5623       // lvx  Vlo, 0, Rb_plus_15
5624       addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, Vlo,
5625                                      PPCAMode_IR(0, rB_plus_15)) );
5626 
5627       if (IEndianess == Iend_LE)
5628          // vperm Vt, Vhi, Vlo, Vp
5629          addInstr(env, PPCInstr_AvPerm( v_dst, Vlo, Vhi, Vp ));
5630       else
5631          // vperm Vt, Vhi, Vlo, Vp
5632          addInstr(env, PPCInstr_AvPerm( v_dst, Vhi, Vlo, Vp ));
5633 
5634       return v_dst;
5635    }
5636 
5637    if (e->tag == Iex_Unop) {
5638       switch (e->Iex.Unop.op) {
5639 
5640       case Iop_F16toF64x2:
5641          {
5642             HReg dst = newVRegV(env);
5643             HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5644             /* Note: PPC only coverts the 16-bt value in the upper word
5645              *       to a 64-bit value stored in the upper word.  The
5646              *       contents of the lower word is undefined.
5647              */
5648             addInstr(env, PPCInstr_AvUnary(Pav_F16toF64x2, dst, arg));
5649             return dst;
5650          }
5651 
5652       case Iop_F64toF16x2:
5653          {
5654             HReg dst = newVRegV(env);
5655             HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5656             /* Note: PPC only coverts the 64-bt value in the upper 64-bit of V128
5657              * to a 16-bit value stored in the upper 64-bits of the result
5658              * V128.  The contents of the lower 64-bits is undefined.
5659              */
5660             addInstr(env, PPCInstr_AvUnary(Pav_F64toF16x2, dst, arg));
5661             return dst;
5662          }
5663 
5664       case Iop_F16toF32x4:
5665          {
5666             HReg src = newVRegV(env);
5667             HReg dst = newVRegV(env);
5668             HReg arg = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
5669             PPCAMode *am_off0, *am_off8;
5670             HReg r_aligned16;
5671 
5672             vassert(mode64);
5673             /* need to put I64 src into upper 64-bits of vector register,
5674                use stack */
5675             sub_from_sp( env, 32 );     // Move SP down
5676 
5677             /* Get a quadword aligned address within our stack space */
5678             r_aligned16 = get_sp_aligned16( env );
5679             am_off0  = PPCAMode_IR( 0, r_aligned16 );
5680             am_off8  = PPCAMode_IR( 8, r_aligned16 );
5681 
5682             /* Store I64 to stack */
5683 
5684             if (IEndianess == Iend_LE) {
5685                addInstr(env, PPCInstr_Store( 8, am_off8, arg, mode64 ));
5686             } else {
5687                addInstr(env, PPCInstr_Store( 8, am_off0, arg, mode64 ));
5688             }
5689 
5690             /* Fetch new v128 src back from stack. */
5691             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, src, am_off0));
5692 
5693             /* issue instruction */
5694             addInstr(env, PPCInstr_AvUnary(Pav_F16toF32x4, dst, src));
5695             add_to_sp( env, 32 );          // Reset SP
5696 
5697             return dst;
5698          }
5699 
5700       case Iop_F32toF16x4:
5701          {
5702             HReg dst = newVRegI(env);
5703             HReg tmp = newVRegV(env);
5704             HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5705             PPCAMode *am_off0, *am_off8;
5706             HReg r_aligned16;
5707 
5708             /* Instruction returns a V128, the Iop_F32toF16x4 needs to return
5709              * I64.  Move the upper 64-bits from the instruction to an I64 via
5710              * the stack and return it.
5711              */
5712             sub_from_sp( env, 32 );     // Move SP down
5713 
5714             addInstr(env, PPCInstr_AvUnary(Pav_F32toF16x4, tmp, arg));
5715 
5716             /* Get a quadword aligned address within our stack space */
5717             r_aligned16 = get_sp_aligned16( env );
5718             am_off0  = PPCAMode_IR( 0, r_aligned16 );
5719             am_off8  = PPCAMode_IR( 8, r_aligned16 );
5720 
5721             /* Store v128 tmp to stack. */
5722             addInstr(env, PPCInstr_AvLdSt(False/*store*/, 16, tmp, am_off0));
5723 
5724             /* Fetch I64 from stack */
5725             if (IEndianess == Iend_LE) {
5726                addInstr(env, PPCInstr_Load( 8, dst, am_off8, mode64 ));
5727             } else {
5728                addInstr(env, PPCInstr_Load( 8, dst, am_off0, mode64 ));
5729             }
5730 
5731             add_to_sp( env, 32 );          // Reset SP
5732             return dst;
5733          }
5734 
5735       case Iop_NotV128: {
5736          HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5737          HReg dst = newVRegV(env);
5738          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, arg));
5739          return dst;
5740       }
5741 
5742       case Iop_CmpNEZ8x16: {
5743          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5744          HReg zero = newVRegV(env);
5745          HReg dst  = newVRegV(env);
5746          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
5747          addInstr(env, PPCInstr_AvBin8x16(Pav_CMPEQU, dst, arg, zero));
5748          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5749          return dst;
5750       }
5751 
5752       case Iop_CmpNEZ16x8: {
5753          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5754          HReg zero = newVRegV(env);
5755          HReg dst  = newVRegV(env);
5756          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
5757          addInstr(env, PPCInstr_AvBin16x8(Pav_CMPEQU, dst, arg, zero));
5758          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5759          return dst;
5760       }
5761 
5762       case Iop_CmpNEZ32x4: {
5763          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5764          HReg zero = newVRegV(env);
5765          HReg dst  = newVRegV(env);
5766          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
5767          addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, dst, arg, zero));
5768          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5769          return dst;
5770       }
5771 
5772       case Iop_CmpNEZ64x2: {
5773          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5774          HReg zero = newVRegV(env);
5775          HReg dst  = newVRegV(env);
5776          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
5777          addInstr(env, PPCInstr_AvBin64x2(Pav_CMPEQU, dst, arg, zero));
5778          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5779          return dst;
5780       }
5781 
5782       case Iop_RecipEst32Fx4: fpop = Pavfp_RCPF;    goto do_32Fx4_unary;
5783       case Iop_RSqrtEst32Fx4: fpop = Pavfp_RSQRTF;  goto do_32Fx4_unary;
5784       case Iop_I32UtoFx4:     fpop = Pavfp_CVTU2F;  goto do_32Fx4_unary;
5785       case Iop_I32StoFx4:     fpop = Pavfp_CVTS2F;  goto do_32Fx4_unary;
5786       case Iop_QFtoI32Ux4_RZ: fpop = Pavfp_QCVTF2U; goto do_32Fx4_unary;
5787       case Iop_QFtoI32Sx4_RZ: fpop = Pavfp_QCVTF2S; goto do_32Fx4_unary;
5788       case Iop_RoundF32x4_RM: fpop = Pavfp_ROUNDM;  goto do_32Fx4_unary;
5789       case Iop_RoundF32x4_RP: fpop = Pavfp_ROUNDP;  goto do_32Fx4_unary;
5790       case Iop_RoundF32x4_RN: fpop = Pavfp_ROUNDN;  goto do_32Fx4_unary;
5791       case Iop_RoundF32x4_RZ: fpop = Pavfp_ROUNDZ;  goto do_32Fx4_unary;
5792       do_32Fx4_unary:
5793       {
5794          HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5795          HReg dst = newVRegV(env);
5796          addInstr(env, PPCInstr_AvUn32Fx4(fpop, dst, arg));
5797          return dst;
5798       }
5799 
5800       case Iop_32UtoV128: {
5801          HReg r_aligned16, r_zeros;
5802          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
5803          HReg   dst = newVRegV(env);
5804          PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
5805          sub_from_sp( env, 32 );     // Move SP down
5806 
5807          /* Get a quadword aligned address within our stack space */
5808          r_aligned16 = get_sp_aligned16( env );
5809          am_off0  = PPCAMode_IR( 0,  r_aligned16 );
5810          am_off4  = PPCAMode_IR( 4,  r_aligned16 );
5811          am_off8  = PPCAMode_IR( 8,  r_aligned16 );
5812          am_off12 = PPCAMode_IR( 12, r_aligned16 );
5813 
5814          /* Store zeros */
5815          r_zeros = newVRegI(env);
5816          addInstr(env, PPCInstr_LI(r_zeros, 0x0, mode64));
5817          if (IEndianess == Iend_LE)
5818             addInstr(env, PPCInstr_Store( 4, am_off0, r_src, mode64 ));
5819          else
5820             addInstr(env, PPCInstr_Store( 4, am_off0, r_zeros, mode64 ));
5821          addInstr(env, PPCInstr_Store( 4, am_off4, r_zeros, mode64 ));
5822          addInstr(env, PPCInstr_Store( 4, am_off8, r_zeros, mode64 ));
5823 
5824          /* Store r_src in low word of quadword-aligned mem */
5825          if (IEndianess == Iend_LE)
5826             addInstr(env, PPCInstr_Store( 4, am_off12, r_zeros, mode64 ));
5827          else
5828             addInstr(env, PPCInstr_Store( 4, am_off12, r_src, mode64 ));
5829 
5830          /* Load word into low word of quadword vector reg */
5831          if (IEndianess == Iend_LE)
5832             addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off0 ));
5833          else
5834             addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off12 ));
5835 
5836          add_to_sp( env, 32 );       // Reset SP
5837          return dst;
5838       }
5839 
5840       case Iop_Dup8x16:
5841       case Iop_Dup16x8:
5842       case Iop_Dup32x4:
5843          return mk_AvDuplicateRI(env, e->Iex.Unop.arg, IEndianess);
5844 
5845       case Iop_CipherSV128: op = Pav_CIPHERSUBV128; goto do_AvCipherV128Un;
5846       do_AvCipherV128Un: {
5847          HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5848          HReg dst = newVRegV(env);
5849          addInstr(env, PPCInstr_AvCipherV128Unary(op, dst, arg));
5850          return dst;
5851       }
5852 
5853       case Iop_Clz8x16: op = Pav_ZEROCNTBYTE;   goto do_zerocnt;
5854       case Iop_Clz16x8: op = Pav_ZEROCNTHALF;   goto do_zerocnt;
5855       case Iop_Clz32x4: op = Pav_ZEROCNTWORD;   goto do_zerocnt;
5856       case Iop_Clz64x2: op = Pav_ZEROCNTDBL;    goto do_zerocnt;
5857       case Iop_Ctz8x16: op = Pav_TRAILINGZEROCNTBYTE; goto do_zerocnt;
5858       case Iop_Ctz16x8: op = Pav_TRAILINGZEROCNTHALF; goto do_zerocnt;
5859       case Iop_Ctz32x4: op = Pav_TRAILINGZEROCNTWORD; goto do_zerocnt;
5860       case Iop_Ctz64x2: op = Pav_TRAILINGZEROCNTDBL;  goto do_zerocnt;
5861       case Iop_PwBitMtxXpose64x2: op = Pav_BITMTXXPOSE;  goto do_zerocnt;
5862       do_zerocnt:
5863       {
5864         HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5865         HReg dst = newVRegV(env);
5866         addInstr(env, PPCInstr_AvUnary(op, dst, arg));
5867         return dst;
5868       }
5869 
5870       /* BCD Iops */
5871       case Iop_BCD128toI128S:
5872          {
5873             HReg dst  = newVRegV(env);
5874             HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5875             addInstr(env, PPCInstr_AvUnary( Pav_BCD128toI128S, dst, arg ) );
5876             return dst;
5877          }
5878 
5879       case Iop_MulI128by10:       op = Pav_MulI128by10;      goto do_MulI128;
5880       case Iop_MulI128by10Carry:  op = Pav_MulI128by10Carry; goto do_MulI128;
5881       do_MulI128: {
5882             HReg dst = newVRegV(env);
5883             HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5884             addInstr(env, PPCInstr_AvUnary(op, dst, arg));
5885             return dst;
5886          }
5887 
5888       default:
5889          break;
5890       } /* switch (e->Iex.Unop.op) */
5891    } /* if (e->tag == Iex_Unop) */
5892 
5893    if (e->tag == Iex_Binop) {
5894       switch (e->Iex.Binop.op) {
5895 
5896       case Iop_64HLtoV128: {
5897          if (!mode64) {
5898             HReg     r3, r2, r1, r0, r_aligned16;
5899             PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
5900             HReg     dst = newVRegV(env);
5901             /* do this via the stack (easy, convenient, etc) */
5902             sub_from_sp( env, 32 );        // Move SP down
5903 
5904             // get a quadword aligned address within our stack space
5905             r_aligned16 = get_sp_aligned16( env );
5906             am_off0  = PPCAMode_IR( 0,  r_aligned16 );
5907             am_off4  = PPCAMode_IR( 4,  r_aligned16 );
5908             am_off8  = PPCAMode_IR( 8,  r_aligned16 );
5909             am_off12 = PPCAMode_IR( 12, r_aligned16 );
5910 
5911             /* Do the less significant 64 bits */
5912             iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2, IEndianess);
5913             addInstr(env, PPCInstr_Store( 4, am_off12, r0, mode64 ));
5914             addInstr(env, PPCInstr_Store( 4, am_off8,  r1, mode64 ));
5915             /* Do the more significant 64 bits */
5916             iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1, IEndianess);
5917             addInstr(env, PPCInstr_Store( 4, am_off4, r2, mode64 ));
5918             addInstr(env, PPCInstr_Store( 4, am_off0, r3, mode64 ));
5919 
5920             /* Fetch result back from stack. */
5921             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
5922 
5923             add_to_sp( env, 32 );          // Reset SP
5924             return dst;
5925          } else {
5926             HReg     rHi = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
5927             HReg     rLo = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
5928             HReg     dst = newVRegV(env);
5929             HReg     r_aligned16;
5930             PPCAMode *am_off0, *am_off8;
5931             /* do this via the stack (easy, convenient, etc) */
5932             sub_from_sp( env, 32 );        // Move SP down
5933 
5934             // get a quadword aligned address within our stack space
5935             r_aligned16 = get_sp_aligned16( env );
5936             am_off0  = PPCAMode_IR( 0,  r_aligned16 );
5937             am_off8  = PPCAMode_IR( 8,  r_aligned16 );
5938 
5939             /* Store 2*I64 to stack */
5940             if (IEndianess == Iend_LE) {
5941                addInstr(env, PPCInstr_Store( 8, am_off0, rLo, mode64 ));
5942                addInstr(env, PPCInstr_Store( 8, am_off8, rHi, mode64 ));
5943             } else {
5944                addInstr(env, PPCInstr_Store( 8, am_off0, rHi, mode64 ));
5945                addInstr(env, PPCInstr_Store( 8, am_off8, rLo, mode64 ));
5946             }
5947             /* Fetch result back from stack. */
5948             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
5949 
5950             add_to_sp( env, 32 );          // Reset SP
5951             return dst;
5952          }
5953       }
5954 
5955       case Iop_Max32Fx4:   fpop = Pavfp_MAXF;   goto do_32Fx4;
5956       case Iop_Min32Fx4:   fpop = Pavfp_MINF;   goto do_32Fx4;
5957       case Iop_CmpEQ32Fx4: fpop = Pavfp_CMPEQF; goto do_32Fx4;
5958       case Iop_CmpGT32Fx4: fpop = Pavfp_CMPGTF; goto do_32Fx4;
5959       case Iop_CmpGE32Fx4: fpop = Pavfp_CMPGEF; goto do_32Fx4;
5960       do_32Fx4:
5961       {
5962          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5963          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5964          HReg dst = newVRegV(env);
5965          addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
5966          return dst;
5967       }
5968 
5969       case Iop_CmpLE32Fx4: {
5970          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5971          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5972          HReg dst = newVRegV(env);
5973 
5974          /* stay consistent with native ppc compares:
5975             if a left/right lane holds a nan, return zeros for that lane
5976             so: le == NOT(gt OR isNan)
5977           */
5978          HReg isNanLR = newVRegV(env);
5979          HReg isNanL = isNan(env, argL, IEndianess);
5980          HReg isNanR = isNan(env, argR, IEndianess);
5981          addInstr(env, PPCInstr_AvBinary(Pav_OR, isNanLR,
5982                                          isNanL, isNanR));
5983 
5984          addInstr(env, PPCInstr_AvBin32Fx4(Pavfp_CMPGTF, dst,
5985                                            argL, argR));
5986          addInstr(env, PPCInstr_AvBinary(Pav_OR, dst, dst, isNanLR));
5987          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5988          return dst;
5989       }
5990 
5991       case Iop_AndV128:    op = Pav_AND;      goto do_AvBin;
5992       case Iop_OrV128:     op = Pav_OR;       goto do_AvBin;
5993       case Iop_XorV128:    op = Pav_XOR;      goto do_AvBin;
5994       do_AvBin: {
5995          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5996          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5997          HReg dst  = newVRegV(env);
5998          addInstr(env, PPCInstr_AvBinary(op, dst, arg1, arg2));
5999          return dst;
6000       }
6001 
6002       case Iop_Shl8x16:    op = Pav_SHL;    goto do_AvBin8x16;
6003       case Iop_Shr8x16:    op = Pav_SHR;    goto do_AvBin8x16;
6004       case Iop_Sar8x16:    op = Pav_SAR;    goto do_AvBin8x16;
6005       case Iop_Rol8x16:    op = Pav_ROTL;   goto do_AvBin8x16;
6006       case Iop_InterleaveHI8x16: op = Pav_MRGHI;  goto do_AvBin8x16;
6007       case Iop_InterleaveLO8x16: op = Pav_MRGLO;  goto do_AvBin8x16;
6008       case Iop_Add8x16:    op = Pav_ADDU;   goto do_AvBin8x16;
6009       case Iop_QAdd8Ux16:  op = Pav_QADDU;  goto do_AvBin8x16;
6010       case Iop_QAdd8Sx16:  op = Pav_QADDS;  goto do_AvBin8x16;
6011       case Iop_Sub8x16:    op = Pav_SUBU;   goto do_AvBin8x16;
6012       case Iop_QSub8Ux16:  op = Pav_QSUBU;  goto do_AvBin8x16;
6013       case Iop_QSub8Sx16:  op = Pav_QSUBS;  goto do_AvBin8x16;
6014       case Iop_Avg8Ux16:   op = Pav_AVGU;   goto do_AvBin8x16;
6015       case Iop_Avg8Sx16:   op = Pav_AVGS;   goto do_AvBin8x16;
6016       case Iop_Max8Ux16:   op = Pav_MAXU;   goto do_AvBin8x16;
6017       case Iop_Max8Sx16:   op = Pav_MAXS;   goto do_AvBin8x16;
6018       case Iop_Min8Ux16:   op = Pav_MINU;   goto do_AvBin8x16;
6019       case Iop_Min8Sx16:   op = Pav_MINS;   goto do_AvBin8x16;
6020       case Iop_MullEven8Ux16: op = Pav_OMULU;  goto do_AvBin8x16;
6021       case Iop_MullEven8Sx16: op = Pav_OMULS;  goto do_AvBin8x16;
6022       case Iop_CmpEQ8x16:  op = Pav_CMPEQU; goto do_AvBin8x16;
6023       case Iop_CmpGT8Ux16: op = Pav_CMPGTU; goto do_AvBin8x16;
6024       case Iop_CmpGT8Sx16: op = Pav_CMPGTS; goto do_AvBin8x16;
6025       case Iop_PolynomialMulAdd8x16: op = Pav_POLYMULADD; goto do_AvBin8x16;
6026       do_AvBin8x16: {
6027          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6028          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6029          HReg dst  = newVRegV(env);
6030          addInstr(env, PPCInstr_AvBin8x16(op, dst, arg1, arg2));
6031          return dst;
6032       }
6033 
6034       case Iop_Shl16x8:    op = Pav_SHL;    goto do_AvBin16x8;
6035       case Iop_Shr16x8:    op = Pav_SHR;    goto do_AvBin16x8;
6036       case Iop_Sar16x8:    op = Pav_SAR;    goto do_AvBin16x8;
6037       case Iop_Rol16x8:    op = Pav_ROTL;   goto do_AvBin16x8;
6038       case Iop_NarrowBin16to8x16:    op = Pav_PACKUU;  goto do_AvBin16x8;
6039       case Iop_QNarrowBin16Uto8Ux16: op = Pav_QPACKUU; goto do_AvBin16x8;
6040       case Iop_QNarrowBin16Sto8Sx16: op = Pav_QPACKSS; goto do_AvBin16x8;
6041       case Iop_InterleaveHI16x8:  op = Pav_MRGHI;  goto do_AvBin16x8;
6042       case Iop_InterleaveLO16x8:  op = Pav_MRGLO;  goto do_AvBin16x8;
6043       case Iop_Add16x8:    op = Pav_ADDU;   goto do_AvBin16x8;
6044       case Iop_QAdd16Ux8:  op = Pav_QADDU;  goto do_AvBin16x8;
6045       case Iop_QAdd16Sx8:  op = Pav_QADDS;  goto do_AvBin16x8;
6046       case Iop_Sub16x8:    op = Pav_SUBU;   goto do_AvBin16x8;
6047       case Iop_QSub16Ux8:  op = Pav_QSUBU;  goto do_AvBin16x8;
6048       case Iop_QSub16Sx8:  op = Pav_QSUBS;  goto do_AvBin16x8;
6049       case Iop_Avg16Ux8:   op = Pav_AVGU;   goto do_AvBin16x8;
6050       case Iop_Avg16Sx8:   op = Pav_AVGS;   goto do_AvBin16x8;
6051       case Iop_Max16Ux8:   op = Pav_MAXU;   goto do_AvBin16x8;
6052       case Iop_Max16Sx8:   op = Pav_MAXS;   goto do_AvBin16x8;
6053       case Iop_Min16Ux8:   op = Pav_MINU;   goto do_AvBin16x8;
6054       case Iop_Min16Sx8:   op = Pav_MINS;   goto do_AvBin16x8;
6055       case Iop_MullEven16Ux8: op = Pav_OMULU;  goto do_AvBin16x8;
6056       case Iop_MullEven16Sx8: op = Pav_OMULS;  goto do_AvBin16x8;
6057       case Iop_CmpEQ16x8:  op = Pav_CMPEQU; goto do_AvBin16x8;
6058       case Iop_CmpGT16Ux8: op = Pav_CMPGTU; goto do_AvBin16x8;
6059       case Iop_CmpGT16Sx8: op = Pav_CMPGTS; goto do_AvBin16x8;
6060       case Iop_PolynomialMulAdd16x8: op = Pav_POLYMULADD; goto do_AvBin16x8;
6061       do_AvBin16x8: {
6062          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6063          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6064          HReg dst  = newVRegV(env);
6065          addInstr(env, PPCInstr_AvBin16x8(op, dst, arg1, arg2));
6066          return dst;
6067       }
6068 
6069       case Iop_Shl32x4:    op = Pav_SHL;    goto do_AvBin32x4;
6070       case Iop_Shr32x4:    op = Pav_SHR;    goto do_AvBin32x4;
6071       case Iop_Sar32x4:    op = Pav_SAR;    goto do_AvBin32x4;
6072       case Iop_Rol32x4:    op = Pav_ROTL;   goto do_AvBin32x4;
6073       case Iop_NarrowBin32to16x8:    op = Pav_PACKUU;  goto do_AvBin32x4;
6074       case Iop_QNarrowBin32Uto16Ux8: op = Pav_QPACKUU; goto do_AvBin32x4;
6075       case Iop_QNarrowBin32Sto16Sx8: op = Pav_QPACKSS; goto do_AvBin32x4;
6076       case Iop_InterleaveHI32x4:  op = Pav_MRGHI;  goto do_AvBin32x4;
6077       case Iop_InterleaveLO32x4:  op = Pav_MRGLO;  goto do_AvBin32x4;
6078       case Iop_Add32x4:    op = Pav_ADDU;   goto do_AvBin32x4;
6079       case Iop_QAdd32Ux4:  op = Pav_QADDU;  goto do_AvBin32x4;
6080       case Iop_QAdd32Sx4:  op = Pav_QADDS;  goto do_AvBin32x4;
6081       case Iop_Sub32x4:    op = Pav_SUBU;   goto do_AvBin32x4;
6082       case Iop_QSub32Ux4:  op = Pav_QSUBU;  goto do_AvBin32x4;
6083       case Iop_QSub32Sx4:  op = Pav_QSUBS;  goto do_AvBin32x4;
6084       case Iop_Avg32Ux4:   op = Pav_AVGU;   goto do_AvBin32x4;
6085       case Iop_Avg32Sx4:   op = Pav_AVGS;   goto do_AvBin32x4;
6086       case Iop_Max32Ux4:   op = Pav_MAXU;   goto do_AvBin32x4;
6087       case Iop_Max32Sx4:   op = Pav_MAXS;   goto do_AvBin32x4;
6088       case Iop_Min32Ux4:   op = Pav_MINU;   goto do_AvBin32x4;
6089       case Iop_Min32Sx4:   op = Pav_MINS;   goto do_AvBin32x4;
6090       case Iop_Mul32x4:    op = Pav_MULU;   goto do_AvBin32x4;
6091       case Iop_MullEven32Ux4: op = Pav_OMULU;  goto do_AvBin32x4;
6092       case Iop_MullEven32Sx4: op = Pav_OMULS;  goto do_AvBin32x4;
6093       case Iop_CmpEQ32x4:  op = Pav_CMPEQU; goto do_AvBin32x4;
6094       case Iop_CmpGT32Ux4: op = Pav_CMPGTU; goto do_AvBin32x4;
6095       case Iop_CmpGT32Sx4: op = Pav_CMPGTS; goto do_AvBin32x4;
6096       case Iop_CatOddLanes32x4:  op = Pav_CATODD;  goto do_AvBin32x4;
6097       case Iop_CatEvenLanes32x4: op = Pav_CATEVEN; goto do_AvBin32x4;
6098       case Iop_PolynomialMulAdd32x4: op = Pav_POLYMULADD; goto do_AvBin32x4;
6099       do_AvBin32x4: {
6100          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6101          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6102          HReg dst  = newVRegV(env);
6103          addInstr(env, PPCInstr_AvBin32x4(op, dst, arg1, arg2));
6104          return dst;
6105       }
6106 
6107       case Iop_Shl64x2:    op = Pav_SHL;    goto do_AvBin64x2;
6108       case Iop_Shr64x2:    op = Pav_SHR;    goto do_AvBin64x2;
6109       case Iop_Sar64x2:    op = Pav_SAR;    goto do_AvBin64x2;
6110       case Iop_Rol64x2:    op = Pav_ROTL;   goto do_AvBin64x2;
6111       case Iop_NarrowBin64to32x4:    op = Pav_PACKUU;  goto do_AvBin64x2;
6112       case Iop_QNarrowBin64Sto32Sx4: op = Pav_QPACKSS; goto do_AvBin64x2;
6113       case Iop_QNarrowBin64Uto32Ux4: op = Pav_QPACKUU; goto do_AvBin64x2;
6114       case Iop_InterleaveHI64x2:  op = Pav_MRGHI;  goto do_AvBin64x2;
6115       case Iop_InterleaveLO64x2:  op = Pav_MRGLO;  goto do_AvBin64x2;
6116       case Iop_Add64x2:    op = Pav_ADDU;   goto do_AvBin64x2;
6117       case Iop_Sub64x2:    op = Pav_SUBU;   goto do_AvBin64x2;
6118       case Iop_Max64Ux2:   op = Pav_MAXU;   goto do_AvBin64x2;
6119       case Iop_Max64Sx2:   op = Pav_MAXS;   goto do_AvBin64x2;
6120       case Iop_Min64Ux2:   op = Pav_MINU;   goto do_AvBin64x2;
6121       case Iop_Min64Sx2:   op = Pav_MINS;   goto do_AvBin64x2;
6122       case Iop_CmpEQ64x2:  op = Pav_CMPEQU; goto do_AvBin64x2;
6123       case Iop_CmpGT64Ux2: op = Pav_CMPGTU; goto do_AvBin64x2;
6124       case Iop_CmpGT64Sx2: op = Pav_CMPGTS; goto do_AvBin64x2;
6125       case Iop_PolynomialMulAdd64x2: op = Pav_POLYMULADD; goto do_AvBin64x2;
6126       do_AvBin64x2: {
6127          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6128          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6129          HReg dst  = newVRegV(env);
6130          addInstr(env, PPCInstr_AvBin64x2(op, dst, arg1, arg2));
6131          return dst;
6132       }
6133 
6134       case Iop_ShlN8x16: op = Pav_SHL; goto do_AvShift8x16;
6135       case Iop_SarN8x16: op = Pav_SAR; goto do_AvShift8x16;
6136       do_AvShift8x16: {
6137          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6138          HReg dst    = newVRegV(env);
6139          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
6140          addInstr(env, PPCInstr_AvBin8x16(op, dst, r_src, v_shft));
6141          return dst;
6142       }
6143 
6144       case Iop_ShlN16x8: op = Pav_SHL; goto do_AvShift16x8;
6145       case Iop_ShrN16x8: op = Pav_SHR; goto do_AvShift16x8;
6146       case Iop_SarN16x8: op = Pav_SAR; goto do_AvShift16x8;
6147       do_AvShift16x8: {
6148          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6149          HReg dst    = newVRegV(env);
6150          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
6151          addInstr(env, PPCInstr_AvBin16x8(op, dst, r_src, v_shft));
6152          return dst;
6153       }
6154 
6155       case Iop_ShlN32x4: op = Pav_SHL; goto do_AvShift32x4;
6156       case Iop_ShrN32x4: op = Pav_SHR; goto do_AvShift32x4;
6157       case Iop_SarN32x4: op = Pav_SAR; goto do_AvShift32x4;
6158       do_AvShift32x4: {
6159          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6160          HReg dst    = newVRegV(env);
6161          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
6162          addInstr(env, PPCInstr_AvBin32x4(op, dst, r_src, v_shft));
6163          return dst;
6164       }
6165 
6166       case Iop_ShlN64x2: op = Pav_SHL; goto do_AvShift64x2;
6167       case Iop_ShrN64x2: op = Pav_SHR; goto do_AvShift64x2;
6168       case Iop_SarN64x2: op = Pav_SAR; goto do_AvShift64x2;
6169       do_AvShift64x2: {
6170          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6171          HReg dst    = newVRegV(env);
6172          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
6173          addInstr(env, PPCInstr_AvBin64x2(op, dst, r_src, v_shft));
6174          return dst;
6175       }
6176 
6177       case Iop_ShrV128: op = Pav_SHR; goto do_AvShiftV128;
6178       case Iop_ShlV128: op = Pav_SHL; goto do_AvShiftV128;
6179       do_AvShiftV128: {
6180          HReg dst    = newVRegV(env);
6181          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6182          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
6183          /* Note: shift value gets masked by 127 */
6184          addInstr(env, PPCInstr_AvBinary(op, dst, r_src, v_shft));
6185          return dst;
6186       }
6187 
6188       case Iop_Perm8x16: {
6189          HReg dst   = newVRegV(env);
6190          HReg v_src = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6191          HReg v_ctl = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6192          addInstr(env, PPCInstr_AvPerm(dst, v_src, v_src, v_ctl));
6193          return dst;
6194       }
6195 
6196       case Iop_CipherV128:  op = Pav_CIPHERV128;   goto do_AvCipherV128;
6197       case Iop_CipherLV128: op = Pav_CIPHERLV128;  goto do_AvCipherV128;
6198       case Iop_NCipherV128: op = Pav_NCIPHERV128;  goto do_AvCipherV128;
6199       case Iop_NCipherLV128:op = Pav_NCIPHERLV128; goto do_AvCipherV128;
6200       do_AvCipherV128: {
6201          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6202          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6203          HReg dst  = newVRegV(env);
6204          addInstr(env, PPCInstr_AvCipherV128Binary(op, dst, arg1, arg2));
6205          return dst;
6206       }
6207 
6208       case Iop_SHA256:op = Pav_SHA256; goto do_AvHashV128;
6209       case Iop_SHA512:op = Pav_SHA512; goto do_AvHashV128;
6210       do_AvHashV128: {
6211          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6212          HReg dst  = newVRegV(env);
6213          PPCRI* s_field = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
6214          addInstr(env, PPCInstr_AvHashV128Binary(op, dst, arg1, s_field));
6215          return dst;
6216       }
6217 
6218       /* BCD Iops */
6219       case Iop_I128StoBCD128:
6220          {
6221             HReg dst = newVRegV(env);
6222             HReg arg = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6223             PPCRI* ps = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
6224 
6225             addInstr(env, PPCInstr_AvBinaryInt( Pav_I128StoBCD128, dst, arg,
6226                                                 ps ) );
6227             return dst;
6228          }
6229 
6230       case Iop_MulI128by10E:       op = Pav_MulI128by10E;      goto do_MulI128E;
6231       case Iop_MulI128by10ECarry:  op = Pav_MulI128by10ECarry; goto do_MulI128E;
6232       do_MulI128E: {
6233             HReg dst  = newVRegV(env);
6234             HReg argL = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6235             HReg argR = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6236             addInstr(env, PPCInstr_AvBinary(op, dst, argL, argR));
6237             return dst;
6238          }
6239 
6240       case Iop_BCDAdd:op = Pav_BCDAdd; goto do_AvBCDV128;
6241       case Iop_BCDSub:op = Pav_BCDSub; goto do_AvBCDV128;
6242       do_AvBCDV128: {
6243          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6244          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6245          HReg dst  = newVRegV(env);
6246          addInstr(env, PPCInstr_AvBCDV128Binary(op, dst, arg1, arg2));
6247          return dst;
6248       }
6249 
6250       default:
6251          break;
6252       } /* switch (e->Iex.Binop.op) */
6253    } /* if (e->tag == Iex_Binop) */
6254 
6255    if (e->tag == Iex_Triop) {
6256       IRTriop *triop = e->Iex.Triop.details;
6257       switch (triop->op) {
6258       case Iop_Add32Fx4: fpop = Pavfp_ADDF; goto do_32Fx4_with_rm;
6259       case Iop_Sub32Fx4: fpop = Pavfp_SUBF; goto do_32Fx4_with_rm;
6260       case Iop_Mul32Fx4: fpop = Pavfp_MULF; goto do_32Fx4_with_rm;
6261       do_32Fx4_with_rm:
6262       {
6263          HReg argL = iselVecExpr(env, triop->arg2, IEndianess);
6264          HReg argR = iselVecExpr(env, triop->arg3, IEndianess);
6265          HReg dst  = newVRegV(env);
6266          /* FIXME: this is bogus, in the sense that Altivec ignores
6267             FPSCR.RM, at least for some FP operations.  So setting the
6268             RM is pointless.  This is only really correct in the case
6269             where the RM is known, at JIT time, to be Irrm_NEAREST,
6270             since -- at least for Altivec FP add/sub/mul -- the
6271             emitted insn is hardwired to round to nearest. */
6272          set_FPU_rounding_mode(env, triop->arg1, IEndianess);
6273          addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
6274          return dst;
6275       }
6276 
6277       default:
6278          break;
6279       } /* switch (e->Iex.Triop.op) */
6280    } /* if (e->tag == Iex_Trinop) */
6281 
6282 
6283    if (e->tag == Iex_Const ) {
6284       vassert(e->Iex.Const.con->tag == Ico_V128);
6285       if (e->Iex.Const.con->Ico.V128 == 0x0000) {
6286          return generate_zeroes_V128(env);
6287       }
6288       else if (e->Iex.Const.con->Ico.V128 == 0xffff) {
6289          return generate_ones_V128(env);
6290       }
6291    }
6292 
6293    vex_printf("iselVecExpr(ppc) (subarch = %s): can't reduce\n",
6294               LibVEX_ppVexHwCaps(mode64 ? VexArchPPC64 : VexArchPPC32,
6295                                  env->hwcaps));
6296    ppIRExpr(e);
6297    vpanic("iselVecExpr_wrk(ppc)");
6298 }
6299 
6300 
6301 /*---------------------------------------------------------*/
6302 /*--- ISEL: Statements                                  ---*/
6303 /*---------------------------------------------------------*/
6304 
iselStmt(ISelEnv * env,IRStmt * stmt,IREndness IEndianess)6305 static void iselStmt ( ISelEnv* env, IRStmt* stmt, IREndness IEndianess )
6306 {
6307    Bool mode64 = env->mode64;
6308    if (vex_traceflags & VEX_TRACE_VCODE) {
6309       vex_printf("\n -- ");
6310       ppIRStmt(stmt);
6311       vex_printf("\n");
6312    }
6313 
6314    switch (stmt->tag) {
6315 
6316    /* --------- STORE --------- */
6317    case Ist_Store: {
6318       IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
6319       IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
6320       IREndness end   = stmt->Ist.Store.end;
6321 
6322       if (end != IEndianess)
6323          goto stmt_fail;
6324       if (!mode64 && (tya != Ity_I32))
6325          goto stmt_fail;
6326       if (mode64 && (tya != Ity_I64))
6327          goto stmt_fail;
6328 
6329       if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
6330           (mode64 && (tyd == Ity_I64))) {
6331          PPCAMode* am_addr
6332             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6333                                  IEndianess);
6334          HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data, IEndianess);
6335          addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(tyd)),
6336                                        am_addr, r_src, mode64 ));
6337          return;
6338       }
6339       if (tyd == Ity_F64) {
6340          PPCAMode* am_addr
6341             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6342                                  IEndianess);
6343          HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data, IEndianess);
6344          addInstr(env,
6345                   PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
6346          return;
6347       }
6348       if (tyd == Ity_F32) {
6349          PPCAMode* am_addr
6350             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6351                                  IEndianess);
6352          HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data, IEndianess);
6353          addInstr(env,
6354                   PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
6355          return;
6356       }
6357       if (tyd == Ity_D64) {
6358          PPCAMode* am_addr
6359             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6360                                  IEndianess);
6361          HReg fr_src = iselDfp64Expr(env, stmt->Ist.Store.data, IEndianess);
6362          addInstr(env,
6363                   PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
6364          return;
6365       }
6366       if (tyd == Ity_D32) {
6367          PPCAMode* am_addr
6368             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6369                                  IEndianess);
6370          HReg fr_src = iselDfp32Expr(env, stmt->Ist.Store.data, IEndianess);
6371          addInstr(env,
6372                   PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
6373          return;
6374       }
6375       if (tyd == Ity_V128) {
6376          PPCAMode* am_addr
6377             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6378                                  IEndianess);
6379          HReg v_src = iselVecExpr(env, stmt->Ist.Store.data, IEndianess);
6380          addInstr(env,
6381                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
6382          return;
6383       }
6384       if (tyd == Ity_I64 && !mode64) {
6385          /* Just calculate the address in the register.  Life is too
6386             short to arse around trying and possibly failing to adjust
6387             the offset in a 'reg+offset' style amode. */
6388          HReg rHi32, rLo32;
6389          HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr, IEndianess);
6390          iselInt64Expr( &rHi32, &rLo32, env, stmt->Ist.Store.data,
6391                         IEndianess );
6392          addInstr(env, PPCInstr_Store( 4/*byte-store*/,
6393                                        PPCAMode_IR( 0, r_addr ),
6394                                        rHi32,
6395                                        False/*32-bit insn please*/) );
6396          addInstr(env, PPCInstr_Store( 4/*byte-store*/,
6397                                        PPCAMode_IR( 4, r_addr ),
6398                                        rLo32,
6399                                        False/*32-bit insn please*/) );
6400          return;
6401       }
6402       break;
6403    }
6404 
6405    /* --------- PUT --------- */
6406    case Ist_Put: {
6407       IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
6408       if (ty == Ity_I8  || ty == Ity_I16 ||
6409           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
6410          HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data, IEndianess);
6411          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
6412                                           GuestStatePtr(mode64) );
6413          addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(ty)),
6414                                        am_addr, r_src, mode64 ));
6415          return;
6416       }
6417       if (!mode64 && ty == Ity_I64) {
6418          HReg rHi, rLo;
6419          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
6420                                            GuestStatePtr(mode64) );
6421          PPCAMode* am_addr4 = advance4(env, am_addr);
6422          iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Put.data, IEndianess);
6423          addInstr(env, PPCInstr_Store( 4, am_addr,  rHi, mode64 ));
6424          addInstr(env, PPCInstr_Store( 4, am_addr4, rLo, mode64 ));
6425          return;
6426       }
6427       if (ty == Ity_I128) {
6428          HReg rHi, rLo;
6429          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
6430                                            GuestStatePtr(mode64) );
6431          PPCAMode* am_addr4 = advance4(env, am_addr);
6432 
6433          iselInt128Expr(&rHi,&rLo, env, stmt->Ist.Put.data, IEndianess);
6434          addInstr(env, PPCInstr_Store( 4, am_addr,  rHi, mode64 ));
6435          addInstr(env, PPCInstr_Store( 4, am_addr4, rLo, mode64 ));
6436          return;
6437       }
6438       if (ty == Ity_F128) {
6439          /* Guest state vectors are 16byte aligned,
6440             so don't need to worry here */
6441          HReg v_src = iselFp128Expr(env, stmt->Ist.Put.data, IEndianess);
6442 
6443          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
6444                                            GuestStatePtr(mode64) );
6445          addInstr(env,
6446                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
6447          return;
6448       }
6449       if (ty == Ity_V128) {
6450          /* Guest state vectors are 16byte aligned,
6451             so don't need to worry here */
6452          HReg v_src = iselVecExpr(env, stmt->Ist.Put.data, IEndianess);
6453          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
6454                                            GuestStatePtr(mode64) );
6455          addInstr(env,
6456                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
6457          return;
6458       }
6459       if (ty == Ity_F64) {
6460          HReg fr_src = iselDblExpr(env, stmt->Ist.Put.data, IEndianess);
6461          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
6462                                           GuestStatePtr(mode64) );
6463          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
6464                                         fr_src, am_addr ));
6465          return;
6466       }
6467       if (ty == Ity_D32) {
6468          /* The 32-bit value is stored in a 64-bit register */
6469          HReg fr_src = iselDfp32Expr( env, stmt->Ist.Put.data, IEndianess );
6470          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
6471                                           GuestStatePtr(mode64) );
6472          addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8,
6473                                          fr_src, am_addr ) );
6474          return;
6475       }
6476       if (ty == Ity_D64) {
6477          HReg fr_src = iselDfp64Expr( env, stmt->Ist.Put.data, IEndianess );
6478          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
6479                                           GuestStatePtr(mode64) );
6480          addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8, fr_src, am_addr ) );
6481          return;
6482       }
6483       break;
6484    }
6485 
6486    /* --------- Indexed PUT --------- */
6487    case Ist_PutI: {
6488       IRPutI *puti = stmt->Ist.PutI.details;
6489 
6490       PPCAMode* dst_am
6491          = genGuestArrayOffset(
6492               env, puti->descr,
6493               puti->ix, puti->bias,
6494               IEndianess );
6495       IRType ty = typeOfIRExpr(env->type_env, puti->data);
6496       if (mode64 && ty == Ity_I64) {
6497          HReg r_src = iselWordExpr_R(env, puti->data, IEndianess);
6498          addInstr(env, PPCInstr_Store( toUChar(8),
6499                                        dst_am, r_src, mode64 ));
6500          return;
6501       }
6502       if ((!mode64) && ty == Ity_I32) {
6503          HReg r_src = iselWordExpr_R(env, puti->data, IEndianess);
6504          addInstr(env, PPCInstr_Store( toUChar(4),
6505                                        dst_am, r_src, mode64 ));
6506          return;
6507       }
6508       break;
6509    }
6510 
6511    /* --------- TMP --------- */
6512    case Ist_WrTmp: {
6513       IRTemp tmp = stmt->Ist.WrTmp.tmp;
6514       IRType ty = typeOfIRTemp(env->type_env, tmp);
6515       if (ty == Ity_I8  || ty == Ity_I16 ||
6516           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
6517          HReg r_dst = lookupIRTemp(env, tmp);
6518          HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data, IEndianess);
6519          addInstr(env, mk_iMOVds_RR( r_dst, r_src ));
6520          return;
6521       }
6522       if (!mode64 && ty == Ity_I64) {
6523          HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
6524 
6525          iselInt64Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data,
6526                        IEndianess);
6527          lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
6528          addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
6529          addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
6530          return;
6531       }
6532       if (mode64 && ty == Ity_I128) {
6533          HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
6534          iselInt128Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data,
6535                         IEndianess);
6536          lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
6537          addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
6538          addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
6539          return;
6540       }
6541       if (!mode64 && ty == Ity_I128) {
6542          HReg r_srcHi, r_srcMedHi, r_srcMedLo, r_srcLo;
6543          HReg r_dstHi, r_dstMedHi, r_dstMedLo, r_dstLo;
6544 
6545          iselInt128Expr_to_32x4(&r_srcHi, &r_srcMedHi,
6546                                 &r_srcMedLo, &r_srcLo,
6547                                 env, stmt->Ist.WrTmp.data, IEndianess);
6548 
6549          lookupIRTempQuad( &r_dstHi, &r_dstMedHi, &r_dstMedLo,
6550                            &r_dstLo, env, tmp);
6551 
6552          addInstr(env, mk_iMOVds_RR(r_dstHi,    r_srcHi) );
6553          addInstr(env, mk_iMOVds_RR(r_dstMedHi, r_srcMedHi) );
6554          addInstr(env, mk_iMOVds_RR(r_dstMedLo, r_srcMedLo) );
6555          addInstr(env, mk_iMOVds_RR(r_dstLo,    r_srcLo) );
6556          return;
6557       }
6558       if (ty == Ity_I1) {
6559          PPCCondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data,
6560                                          IEndianess);
6561          HReg r_dst = lookupIRTemp(env, tmp);
6562          addInstr(env, PPCInstr_Set(cond, r_dst));
6563          return;
6564       }
6565       if (ty == Ity_F64) {
6566          HReg fr_dst = lookupIRTemp(env, tmp);
6567          HReg fr_src = iselDblExpr(env, stmt->Ist.WrTmp.data, IEndianess);
6568          addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
6569          return;
6570       }
6571       if (ty == Ity_F32) {
6572          HReg fr_dst = lookupIRTemp(env, tmp);
6573          HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data, IEndianess);
6574          addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
6575          return;
6576       }
6577       if (ty == Ity_D32) {
6578          HReg fr_dst = lookupIRTemp(env, tmp);
6579          HReg fr_src = iselDfp32Expr(env, stmt->Ist.WrTmp.data, IEndianess);
6580          addInstr(env, PPCInstr_Dfp64Unary(Pfp_MOV, fr_dst, fr_src));
6581          return;
6582       }
6583       if (ty == Ity_F128) {
6584          HReg v_dst = lookupIRTemp(env, tmp);
6585          HReg v_src = iselFp128Expr(env, stmt->Ist.WrTmp.data, IEndianess);
6586          addInstr(env, PPCInstr_AvUnary(Pav_MOV, v_dst, v_src));
6587          return;
6588       }
6589       if (ty == Ity_V128) {
6590          HReg v_dst = lookupIRTemp(env, tmp);
6591          HReg v_src = iselVecExpr(env, stmt->Ist.WrTmp.data, IEndianess);
6592          addInstr(env, PPCInstr_AvUnary(Pav_MOV, v_dst, v_src));
6593          return;
6594       }
6595       if (ty == Ity_D64) {
6596          HReg fr_dst = lookupIRTemp( env, tmp );
6597          HReg fr_src = iselDfp64Expr( env, stmt->Ist.WrTmp.data, IEndianess );
6598          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dst, fr_src ) );
6599          return;
6600       }
6601       if (ty == Ity_D128) {
6602          HReg fr_srcHi, fr_srcLo, fr_dstHi, fr_dstLo;
6603 	 //         lookupDfp128IRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
6604          lookupIRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
6605          iselDfp128Expr( &fr_srcHi, &fr_srcLo, env, stmt->Ist.WrTmp.data,
6606                          IEndianess );
6607          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstHi, fr_srcHi ) );
6608          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstLo, fr_srcLo ) );
6609          return;
6610       }
6611       break;
6612    }
6613 
6614    /* --------- Load Linked or Store Conditional --------- */
6615    case Ist_LLSC: {
6616       IRTemp res    = stmt->Ist.LLSC.result;
6617       IRType tyRes  = typeOfIRTemp(env->type_env, res);
6618       IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
6619 
6620       if (stmt->Ist.LLSC.end != IEndianess)
6621          goto stmt_fail;
6622       if (!mode64 && (tyAddr != Ity_I32))
6623          goto stmt_fail;
6624       if (mode64 && (tyAddr != Ity_I64))
6625          goto stmt_fail;
6626 
6627       if (stmt->Ist.LLSC.storedata == NULL) {
6628          /* LL */
6629          HReg r_addr = iselWordExpr_R( env, stmt->Ist.LLSC.addr, IEndianess );
6630          HReg r_dst  = lookupIRTemp(env, res);
6631          if (tyRes == Ity_I8) {
6632             addInstr(env, PPCInstr_LoadL( 1, r_dst, r_addr, mode64 ));
6633             return;
6634          }
6635          if (tyRes == Ity_I16) {
6636             addInstr(env, PPCInstr_LoadL( 2, r_dst, r_addr, mode64 ));
6637             return;
6638          }
6639          if (tyRes == Ity_I32) {
6640             addInstr(env, PPCInstr_LoadL( 4, r_dst, r_addr, mode64 ));
6641             return;
6642          }
6643          if (tyRes == Ity_I64 && mode64) {
6644             addInstr(env, PPCInstr_LoadL( 8, r_dst, r_addr, mode64 ));
6645             return;
6646          }
6647          /* fallthru */;
6648       } else {
6649          /* SC */
6650          HReg   r_res  = lookupIRTemp(env, res); /* :: Ity_I1 */
6651          HReg   r_a    = iselWordExpr_R(env, stmt->Ist.LLSC.addr, IEndianess);
6652          HReg   r_src  = iselWordExpr_R(env, stmt->Ist.LLSC.storedata,
6653                                         IEndianess);
6654          HReg   r_tmp  = newVRegI(env);
6655          IRType tyData = typeOfIRExpr(env->type_env,
6656                                       stmt->Ist.LLSC.storedata);
6657          vassert(tyRes == Ity_I1);
6658          if (tyData == Ity_I8 || tyData == Ity_I16 || tyData == Ity_I32 ||
6659             (tyData == Ity_I64 && mode64)) {
6660             int size = 0;
6661 
6662             if (tyData == Ity_I64)
6663                size = 8;
6664             else if (tyData == Ity_I32)
6665                size = 4;
6666             else if (tyData == Ity_I16)
6667                size = 2;
6668             else if (tyData == Ity_I8)
6669                size = 1;
6670 
6671             addInstr(env, PPCInstr_StoreC( size,
6672                                            r_a, r_src, mode64 ));
6673             addInstr(env, PPCInstr_MfCR( r_tmp ));
6674             addInstr(env, PPCInstr_Shft(
6675                              Pshft_SHR,
6676                              env->mode64 ? False : True
6677                                 /*F:64-bit, T:32-bit shift*/,
6678                              r_tmp, r_tmp,
6679                              PPCRH_Imm(False/*unsigned*/, 29)));
6680             /* Probably unnecessary, since the IR dest type is Ity_I1,
6681                and so we are entitled to leave whatever junk we like
6682                drifting round in the upper 31 or 63 bits of r_res.
6683                However, for the sake of conservativeness .. */
6684             addInstr(env, PPCInstr_Alu(
6685                              Palu_AND,
6686                              r_res, r_tmp,
6687                              PPCRH_Imm(False/*signed*/, 1)));
6688             return;
6689          }
6690          /* fallthru */
6691       }
6692       goto stmt_fail;
6693       /*NOTREACHED*/
6694    }
6695 
6696    /* --------- Call to DIRTY helper --------- */
6697    case Ist_Dirty: {
6698       IRDirty* d = stmt->Ist.Dirty.details;
6699 
6700       /* Figure out the return type, if any. */
6701       IRType retty = Ity_INVALID;
6702       if (d->tmp != IRTemp_INVALID)
6703          retty = typeOfIRTemp(env->type_env, d->tmp);
6704 
6705       /* Throw out any return types we don't know about.  The set of
6706          acceptable return types is the same in both 32- and 64-bit
6707          mode, so we don't need to inspect mode64 to make a
6708          decision. */
6709       Bool retty_ok = False;
6710       switch (retty) {
6711          case Ity_INVALID: /* function doesn't return anything */
6712          case Ity_V128:
6713          case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
6714             retty_ok = True; break;
6715          default:
6716             break;
6717       }
6718       if (!retty_ok)
6719          break; /* will go to stmt_fail: */
6720 
6721       /* Marshal args, do the call, clear stack, set the return value
6722          to 0x555..555 if this is a conditional call that returns a
6723          value and the call is skipped. */
6724       UInt   addToSp = 0;
6725       RetLoc rloc    = mk_RetLoc_INVALID();
6726       doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args,
6727                     IEndianess );
6728       vassert(is_sane_RetLoc(rloc));
6729 
6730       /* Now figure out what to do with the returned value, if any. */
6731       switch (retty) {
6732          case Ity_INVALID: {
6733             /* No return value.  Nothing to do. */
6734             vassert(d->tmp == IRTemp_INVALID);
6735             vassert(rloc.pri == RLPri_None);
6736             vassert(addToSp == 0);
6737             return;
6738          }
6739          case Ity_I32: case Ity_I16: case Ity_I8: {
6740             /* The returned value is in %r3.  Park it in the register
6741                associated with tmp. */
6742             HReg r_dst = lookupIRTemp(env, d->tmp);
6743             addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
6744             vassert(rloc.pri == RLPri_Int);
6745             vassert(addToSp == 0);
6746             return;
6747          }
6748          case Ity_I64:
6749             if (mode64) {
6750                /* The returned value is in %r3.  Park it in the register
6751                   associated with tmp. */
6752                HReg r_dst = lookupIRTemp(env, d->tmp);
6753                addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
6754                vassert(rloc.pri == RLPri_Int);
6755                vassert(addToSp == 0);
6756             } else {
6757                /* The returned value is in %r3:%r4.  Park it in the
6758                   register-pair associated with tmp. */
6759                HReg r_dstHi = INVALID_HREG;
6760                HReg r_dstLo = INVALID_HREG;
6761                lookupIRTempPair( &r_dstHi, &r_dstLo, env, d->tmp);
6762                addInstr(env, mk_iMOVds_RR(r_dstHi, hregPPC_GPR3(mode64)));
6763                addInstr(env, mk_iMOVds_RR(r_dstLo, hregPPC_GPR4(mode64)));
6764                vassert(rloc.pri == RLPri_2Int);
6765                vassert(addToSp == 0);
6766             }
6767             return;
6768          case Ity_V128: {
6769             /* The returned value is on the stack, and *retloc tells
6770                us where.  Fish it off the stack and then move the
6771                stack pointer upwards to clear it, as directed by
6772                doHelperCall. */
6773             vassert(rloc.pri == RLPri_V128SpRel);
6774             vassert(addToSp >= 16);
6775             HReg      dst = lookupIRTemp(env, d->tmp);
6776             PPCAMode* am  = PPCAMode_IR(rloc.spOff, StackFramePtr(mode64));
6777             addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, dst, am ));
6778             add_to_sp(env, addToSp);
6779             return;
6780          }
6781          default:
6782             /*NOTREACHED*/
6783             vassert(0);
6784       }
6785    }
6786 
6787    /* --------- MEM FENCE --------- */
6788    case Ist_MBE:
6789       switch (stmt->Ist.MBE.event) {
6790          case Imbe_Fence:
6791             addInstr(env, PPCInstr_MFence());
6792             return;
6793          default:
6794             break;
6795       }
6796       break;
6797 
6798    /* --------- INSTR MARK --------- */
6799    /* Doesn't generate any executable code ... */
6800    case Ist_IMark:
6801        return;
6802 
6803    /* --------- ABI HINT --------- */
6804    /* These have no meaning (denotation in the IR) and so we ignore
6805       them ... if any actually made it this far. */
6806    case Ist_AbiHint:
6807        return;
6808 
6809    /* --------- NO-OP --------- */
6810    /* Fairly self-explanatory, wouldn't you say? */
6811    case Ist_NoOp:
6812        return;
6813 
6814    /* --------- EXIT --------- */
6815    case Ist_Exit: {
6816       IRConst* dst = stmt->Ist.Exit.dst;
6817       if (!mode64 && dst->tag != Ico_U32)
6818          vpanic("iselStmt(ppc): Ist_Exit: dst is not a 32-bit value");
6819       if (mode64 && dst->tag != Ico_U64)
6820          vpanic("iselStmt(ppc64): Ist_Exit: dst is not a 64-bit value");
6821 
6822       PPCCondCode cc    = iselCondCode(env, stmt->Ist.Exit.guard, IEndianess);
6823       PPCAMode*   amCIA = PPCAMode_IR(stmt->Ist.Exit.offsIP,
6824                                       hregPPC_GPR31(mode64));
6825 
6826       /* Case: boring transfer to known address */
6827       if (stmt->Ist.Exit.jk == Ijk_Boring
6828           || stmt->Ist.Exit.jk == Ijk_Call
6829           /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
6830          if (env->chainingAllowed) {
6831             /* .. almost always true .. */
6832             /* Skip the event check at the dst if this is a forwards
6833                edge. */
6834             Bool toFastEP
6835                = mode64
6836                ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
6837                : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
6838             if (0) vex_printf("%s", toFastEP ? "Y" : ",");
6839             addInstr(env, PPCInstr_XDirect(
6840                              mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
6841                                     : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
6842                              amCIA, cc, toFastEP));
6843          } else {
6844             /* .. very occasionally .. */
6845             /* We can't use chaining, so ask for an assisted transfer,
6846                as that's the only alternative that is allowable. */
6847             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst),
6848                                     IEndianess);
6849             addInstr(env, PPCInstr_XAssisted(r, amCIA, cc, Ijk_Boring));
6850          }
6851          return;
6852       }
6853 
6854       /* Case: assisted transfer to arbitrary address */
6855       switch (stmt->Ist.Exit.jk) {
6856          /* Keep this list in sync with that in iselNext below */
6857          case Ijk_ClientReq:
6858          case Ijk_EmFail:
6859          case Ijk_EmWarn:
6860          case Ijk_NoDecode:
6861          case Ijk_NoRedir:
6862          case Ijk_SigBUS:
6863          case Ijk_SigTRAP:
6864          case Ijk_Sys_syscall:
6865          case Ijk_InvalICache:
6866          {
6867             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst),
6868                                     IEndianess);
6869             addInstr(env, PPCInstr_XAssisted(r, amCIA, cc,
6870                                              stmt->Ist.Exit.jk));
6871             return;
6872          }
6873          default:
6874             break;
6875       }
6876 
6877       /* Do we ever expect to see any other kind? */
6878       goto stmt_fail;
6879    }
6880 
6881    default: break;
6882    }
6883   stmt_fail:
6884    ppIRStmt(stmt);
6885    vpanic("iselStmt(ppc)");
6886 }
6887 
6888 
6889 /*---------------------------------------------------------*/
6890 /*--- ISEL: Basic block terminators (Nexts)             ---*/
6891 /*---------------------------------------------------------*/
6892 
iselNext(ISelEnv * env,IRExpr * next,IRJumpKind jk,Int offsIP,IREndness IEndianess)6893 static void iselNext ( ISelEnv* env,
6894                        IRExpr* next, IRJumpKind jk, Int offsIP,
6895                        IREndness IEndianess)
6896 {
6897    if (vex_traceflags & VEX_TRACE_VCODE) {
6898       vex_printf( "\n-- PUT(%d) = ", offsIP);
6899       ppIRExpr( next );
6900       vex_printf( "; exit-");
6901       ppIRJumpKind(jk);
6902       vex_printf( "\n");
6903    }
6904 
6905    PPCCondCode always = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
6906 
6907    /* Case: boring transfer to known address */
6908    if (next->tag == Iex_Const) {
6909       IRConst* cdst = next->Iex.Const.con;
6910       vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
6911       if (jk == Ijk_Boring || jk == Ijk_Call) {
6912          /* Boring transfer to known address */
6913          PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
6914          if (env->chainingAllowed) {
6915             /* .. almost always true .. */
6916             /* Skip the event check at the dst if this is a forwards
6917                edge. */
6918             Bool toFastEP
6919                = env->mode64
6920                ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
6921                : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
6922             if (0) vex_printf("%s", toFastEP ? "X" : ".");
6923             addInstr(env, PPCInstr_XDirect(
6924                              env->mode64 ? (Addr64)cdst->Ico.U64
6925                                          : (Addr64)cdst->Ico.U32,
6926                              amCIA, always, toFastEP));
6927          } else {
6928             /* .. very occasionally .. */
6929             /* We can't use chaining, so ask for an assisted transfer,
6930                as that's the only alternative that is allowable. */
6931             HReg r = iselWordExpr_R(env, next, IEndianess);
6932             addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
6933                                              Ijk_Boring));
6934          }
6935          return;
6936       }
6937    }
6938 
6939    /* Case: call/return (==boring) transfer to any address */
6940    switch (jk) {
6941       case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
6942          HReg       r     = iselWordExpr_R(env, next, IEndianess);
6943          PPCAMode*  amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
6944          if (env->chainingAllowed) {
6945             addInstr(env, PPCInstr_XIndir(r, amCIA, always));
6946          } else {
6947             addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
6948                                              Ijk_Boring));
6949          }
6950          return;
6951       }
6952       default:
6953          break;
6954    }
6955 
6956    /* Case: assisted transfer to arbitrary address */
6957    switch (jk) {
6958       /* Keep this list in sync with that for Ist_Exit above */
6959       case Ijk_ClientReq:
6960       case Ijk_EmFail:
6961       case Ijk_EmWarn:
6962       case Ijk_NoDecode:
6963       case Ijk_NoRedir:
6964       case Ijk_SigBUS:
6965       case Ijk_SigTRAP:
6966       case Ijk_Sys_syscall:
6967       case Ijk_InvalICache:
6968       {
6969          HReg      r     = iselWordExpr_R(env, next, IEndianess);
6970          PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
6971          addInstr(env, PPCInstr_XAssisted(r, amCIA, always, jk));
6972          return;
6973       }
6974       default:
6975          break;
6976    }
6977 
6978    vex_printf( "\n-- PUT(%d) = ", offsIP);
6979    ppIRExpr( next );
6980    vex_printf( "; exit-");
6981    ppIRJumpKind(jk);
6982    vex_printf( "\n");
6983    vassert(0); // are we expecting any other kind?
6984 }
6985 
6986 
6987 /*---------------------------------------------------------*/
6988 /*--- Insn selector top-level                           ---*/
6989 /*---------------------------------------------------------*/
6990 
6991 /* Translate an entire SB to ppc code. */
iselSB_PPC(const IRSB * bb,VexArch arch_host,const VexArchInfo * archinfo_host,const VexAbiInfo * vbi,Int offs_Host_EvC_Counter,Int offs_Host_EvC_FailAddr,Bool chainingAllowed,Bool addProfInc,Addr max_ga)6992 HInstrArray* iselSB_PPC ( const IRSB* bb,
6993                           VexArch      arch_host,
6994                           const VexArchInfo* archinfo_host,
6995                           const VexAbiInfo*  vbi,
6996                           Int offs_Host_EvC_Counter,
6997                           Int offs_Host_EvC_FailAddr,
6998                           Bool chainingAllowed,
6999                           Bool addProfInc,
7000                           Addr max_ga)
7001 
7002 {
7003    Int       i, j;
7004    HReg      hregLo, hregMedLo, hregMedHi, hregHi;
7005    ISelEnv*  env;
7006    UInt      hwcaps_host = archinfo_host->hwcaps;
7007    Bool      mode64 = False;
7008    UInt      mask32, mask64;
7009    PPCAMode *amCounter, *amFailAddr;
7010    IREndness IEndianess;
7011 
7012    vassert(arch_host == VexArchPPC32 || arch_host == VexArchPPC64);
7013    mode64 = arch_host == VexArchPPC64;
7014 
7015    /* do some sanity checks,
7016     * Note: no 32-bit support for ISA 3.0
7017     */
7018    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
7019             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
7020             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
7021 
7022    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
7023             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
7024             | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0;
7025 
7026    if (mode64) {
7027       vassert((hwcaps_host & mask32) == 0);
7028    } else {
7029       vassert((hwcaps_host & mask64) == 0);
7030    }
7031 
7032    /* Check that the host's endianness is as expected. */
7033    vassert((archinfo_host->endness == VexEndnessBE) ||
7034 	   (archinfo_host->endness == VexEndnessLE));
7035 
7036    if (archinfo_host->endness == VexEndnessBE)
7037      IEndianess = Iend_BE;
7038    else
7039      IEndianess = Iend_LE;
7040 
7041    /* Make up an initial environment to use. */
7042    env = LibVEX_Alloc_inline(sizeof(ISelEnv));
7043    env->vreg_ctr = 0;
7044 
7045    /* Are we being ppc32 or ppc64? */
7046    env->mode64 = mode64;
7047 
7048    /* Set up output code array. */
7049    env->code = newHInstrArray();
7050 
7051    /* Copy BB's type env. */
7052    env->type_env = bb->tyenv;
7053 
7054    /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
7055     * change as we go along.
7056     *
7057     * vregmap2 and vregmap3 are only used in 32 bit mode
7058     * for supporting I128 in 32-bit mode
7059     */
7060    env->n_vregmap = bb->tyenv->types_used;
7061    env->vregmapLo    = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
7062    env->vregmapMedLo = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
7063    if (mode64) {
7064       env->vregmapMedHi = NULL;
7065       env->vregmapHi    = NULL;
7066    } else {
7067       env->vregmapMedHi = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
7068       env->vregmapHi    = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
7069    }
7070 
7071    /* and finally ... */
7072    env->chainingAllowed = chainingAllowed;
7073    env->max_ga          = max_ga;
7074    env->hwcaps          = hwcaps_host;
7075    env->previous_rm     = NULL;
7076    env->vbi             = vbi;
7077 
7078    /* For each IR temporary, allocate a suitably-kinded virtual
7079       register. */
7080    j = 0;
7081    for (i = 0; i < env->n_vregmap; i++) {
7082       hregLo = hregMedLo = hregMedHi = hregHi = INVALID_HREG;
7083       switch (bb->tyenv->types[i]) {
7084       case Ity_I1:
7085       case Ity_I8:
7086       case Ity_I16:
7087       case Ity_I32:
7088          if (mode64) {
7089             hregLo = mkHReg(True, HRcInt64, 0, j++);
7090          } else {
7091             hregLo = mkHReg(True, HRcInt32, 0, j++);
7092          }
7093          break;
7094       case Ity_I64:
7095          if (mode64) {
7096             hregLo    = mkHReg(True, HRcInt64, 0, j++);
7097          } else {
7098             hregLo    = mkHReg(True, HRcInt32, 0, j++);
7099             hregMedLo = mkHReg(True, HRcInt32, 0, j++);
7100          }
7101          break;
7102       case Ity_I128:
7103          if (mode64) {
7104             hregLo    = mkHReg(True, HRcInt64, 0, j++);
7105             hregMedLo = mkHReg(True, HRcInt64, 0, j++);
7106          } else {
7107             hregLo    = mkHReg(True, HRcInt32, 0, j++);
7108             hregMedLo = mkHReg(True, HRcInt32, 0, j++);
7109             hregMedHi = mkHReg(True, HRcInt32, 0, j++);
7110             hregHi    = mkHReg(True, HRcInt32, 0, j++);
7111          }
7112          break;
7113       case Ity_F32:
7114       case Ity_F64:
7115          hregLo = mkHReg(True, HRcFlt64, 0, j++);
7116          break;
7117       case Ity_F128:
7118       case Ity_V128:
7119          hregLo = mkHReg(True, HRcVec128, 0, j++);
7120          break;
7121       case Ity_D32:
7122       case Ity_D64:
7123          hregLo = mkHReg(True, HRcFlt64, 0, j++);
7124          break;
7125       case Ity_D128:
7126          hregLo    = mkHReg(True, HRcFlt64, 0, j++);
7127          hregMedLo = mkHReg(True, HRcFlt64, 0, j++);
7128          break;
7129       default:
7130          ppIRType(bb->tyenv->types[i]);
7131          vpanic("iselBB(ppc): IRTemp type");
7132       }
7133       env->vregmapLo[i]    = hregLo;
7134       env->vregmapMedLo[i] = hregMedLo;
7135       if (!mode64) {
7136          env->vregmapMedHi[i] = hregMedHi;
7137          env->vregmapHi[i]    = hregHi;
7138       }
7139    }
7140    env->vreg_ctr = j;
7141 
7142    /* The very first instruction must be an event check. */
7143    amCounter  = PPCAMode_IR(offs_Host_EvC_Counter, hregPPC_GPR31(mode64));
7144    amFailAddr = PPCAMode_IR(offs_Host_EvC_FailAddr, hregPPC_GPR31(mode64));
7145    addInstr(env, PPCInstr_EvCheck(amCounter, amFailAddr));
7146 
7147    /* Possibly a block counter increment (for profiling).  At this
7148       point we don't know the address of the counter, so just pretend
7149       it is zero.  It will have to be patched later, but before this
7150       translation is used, by a call to LibVEX_patchProfCtr. */
7151    if (addProfInc) {
7152       addInstr(env, PPCInstr_ProfInc());
7153    }
7154 
7155    /* Ok, finally we can iterate over the statements. */
7156    for (i = 0; i < bb->stmts_used; i++)
7157       iselStmt(env, bb->stmts[i], IEndianess);
7158 
7159    iselNext(env, bb->next, bb->jumpkind, bb->offsIP, IEndianess);
7160 
7161    /* record the number of vregs we used. */
7162    env->code->n_vregs = env->vreg_ctr;
7163    return env->code;
7164 }
7165 
7166 
7167 /*---------------------------------------------------------------*/
7168 /*--- end                                     host_ppc_isel.c ---*/
7169 /*---------------------------------------------------------------*/
7170