• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                vassert(0); /* AWAITING TEST CASE */
1532             }
1533          }
1534          /* Only 64 expressions need 64bit shifts,
1535             32bit shifts are fine for all others */
1536          if (ty == Ity_I64) {
1537             vassert(mode64);
1538             addInstr(env, PPCInstr_Shft(shftOp, False/*64bit shift*/,
1539                                         r_dst, r_srcL, ri_srcR));
1540          } else {
1541             addInstr(env, PPCInstr_Shft(shftOp, True/*32bit shift*/,
1542                                         r_dst, r_srcL, ri_srcR));
1543          }
1544          return r_dst;
1545       }
1546 
1547       /* How about a div? */
1548       if (e->Iex.Binop.op == Iop_DivS32 ||
1549           e->Iex.Binop.op == Iop_DivU32 ||
1550           e->Iex.Binop.op == Iop_DivS32E ||
1551           e->Iex.Binop.op == Iop_DivU32E) {
1552          Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS32) || (e->Iex.Binop.op == Iop_DivS32E));
1553          HReg r_dst  = newVRegI(env);
1554          HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1555          HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1556          addInstr( env,
1557                       PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivU32E )
1558                                              || ( e->Iex.Binop.op == Iop_DivS32E ) ) ? True
1559                                                                                      : False,
1560                                     syned,
1561                                     True/*32bit div*/,
1562                                     r_dst,
1563                                     r_srcL,
1564                                     r_srcR ) );
1565          return r_dst;
1566       }
1567       if (e->Iex.Binop.op == Iop_DivS64 ||
1568           e->Iex.Binop.op == Iop_DivU64 || e->Iex.Binop.op == Iop_DivS64E
1569           || e->Iex.Binop.op == Iop_DivU64E ) {
1570          Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS64) ||(e->Iex.Binop.op == Iop_DivS64E));
1571          HReg r_dst  = newVRegI(env);
1572          HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1573          HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1574          vassert(mode64);
1575          addInstr( env,
1576                       PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivS64E )
1577                                              || ( e->Iex.Binop.op
1578                                                       == Iop_DivU64E ) ) ? True
1579                                                                          : False,
1580                                     syned,
1581                                     False/*64bit div*/,
1582                                     r_dst,
1583                                     r_srcL,
1584                                     r_srcR ) );
1585          return r_dst;
1586       }
1587 
1588       /* No? Anyone for a mul? */
1589       if (e->Iex.Binop.op == Iop_Mul32
1590           || e->Iex.Binop.op == Iop_Mul64) {
1591          Bool syned       = False;
1592          Bool sz32        = (e->Iex.Binop.op != Iop_Mul64);
1593          HReg r_dst       = newVRegI(env);
1594          HReg r_srcL      = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1595          HReg r_srcR      = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1596          addInstr(env, PPCInstr_MulL(syned, False/*lo32*/, sz32,
1597                                      r_dst, r_srcL, r_srcR));
1598          return r_dst;
1599       }
1600 
1601       /* 32 x 32 -> 64 multiply */
1602       if (mode64
1603           && (e->Iex.Binop.op == Iop_MullU32
1604               || e->Iex.Binop.op == Iop_MullS32)) {
1605          HReg tLo    = newVRegI(env);
1606          HReg tHi    = newVRegI(env);
1607          HReg r_dst  = newVRegI(env);
1608          Bool syned  = toBool(e->Iex.Binop.op == Iop_MullS32);
1609          HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1610          HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1611          addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
1612                                      False/*lo32*/, True/*32bit mul*/,
1613                                      tLo, r_srcL, r_srcR));
1614          addInstr(env, PPCInstr_MulL(syned,
1615                                      True/*hi32*/, True/*32bit mul*/,
1616                                      tHi, r_srcL, r_srcR));
1617          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1618                                      r_dst, tHi, PPCRH_Imm(False,32)));
1619          addInstr(env, PPCInstr_Alu(Palu_OR,
1620                                     r_dst, r_dst, PPCRH_Reg(tLo)));
1621          return r_dst;
1622       }
1623 
1624       /* El-mutanto 3-way compare? */
1625       if (e->Iex.Binop.op == Iop_CmpORD32S
1626           || e->Iex.Binop.op == Iop_CmpORD32U) {
1627          Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD32S);
1628          HReg   dst   = newVRegI(env);
1629          HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1630          PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2,
1631                                         IEndianess);
1632          addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
1633                                     7/*cr*/, srcL, srcR));
1634          addInstr(env, PPCInstr_MfCR(dst));
1635          addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1636                                     PPCRH_Imm(False,7<<1)));
1637          return dst;
1638       }
1639 
1640       if (e->Iex.Binop.op == Iop_CmpORD64S
1641           || e->Iex.Binop.op == Iop_CmpORD64U) {
1642          Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD64S);
1643          HReg   dst   = newVRegI(env);
1644          HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1645          PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2,
1646                                         IEndianess);
1647          vassert(mode64);
1648          addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
1649                                     7/*cr*/, srcL, srcR));
1650          addInstr(env, PPCInstr_MfCR(dst));
1651          addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1652                                     PPCRH_Imm(False,7<<1)));
1653          return dst;
1654       }
1655 
1656       if (e->Iex.Binop.op == Iop_Max32U) {
1657          HReg        r1   = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1658          HReg        r2   = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1659          HReg        rdst = newVRegI(env);
1660          PPCCondCode cc   = mk_PPCCondCode( Pct_TRUE, Pcf_7LT );
1661          addInstr(env, mk_iMOVds_RR(rdst, r1));
1662          addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
1663                                     7/*cr*/, rdst, PPCRH_Reg(r2)));
1664          addInstr(env, PPCInstr_CMov(cc, rdst, PPCRI_Reg(r2)));
1665          return rdst;
1666       }
1667 
1668       if (e->Iex.Binop.op == Iop_32HLto64) {
1669          HReg   r_Hi  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
1670          HReg   r_Lo  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
1671          HReg   r_Tmp = newVRegI(env);
1672          HReg   r_dst = newVRegI(env);
1673          HReg   msk   = newVRegI(env);
1674          vassert(mode64);
1675          /* r_dst = OR( r_Hi<<32, r_Lo ) */
1676          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1677                                      r_dst, r_Hi, PPCRH_Imm(False,32)));
1678          addInstr(env, PPCInstr_LI(msk, 0xFFFFFFFF, mode64));
1679          addInstr(env, PPCInstr_Alu( Palu_AND, r_Tmp, r_Lo,
1680                                      PPCRH_Reg(msk) ));
1681          addInstr(env, PPCInstr_Alu( Palu_OR, r_dst, r_dst,
1682                                      PPCRH_Reg(r_Tmp) ));
1683          return r_dst;
1684       }
1685 
1686       if ((e->Iex.Binop.op == Iop_CmpF64) ||
1687           (e->Iex.Binop.op == Iop_CmpD64) ||
1688           (e->Iex.Binop.op == Iop_CmpD128)) {
1689          HReg fr_srcL;
1690          HReg fr_srcL_lo;
1691          HReg fr_srcR;
1692          HReg fr_srcR_lo;
1693 
1694          HReg r_ccPPC   = newVRegI(env);
1695          HReg r_ccIR    = newVRegI(env);
1696          HReg r_ccIR_b0 = newVRegI(env);
1697          HReg r_ccIR_b2 = newVRegI(env);
1698          HReg r_ccIR_b6 = newVRegI(env);
1699 
1700          if (e->Iex.Binop.op == Iop_CmpF64) {
1701             fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1, IEndianess);
1702             fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
1703             addInstr(env, PPCInstr_FpCmp(r_ccPPC, fr_srcL, fr_srcR));
1704 
1705          } else if (e->Iex.Binop.op == Iop_CmpD64) {
1706             fr_srcL = iselDfp64Expr(env, e->Iex.Binop.arg1, IEndianess);
1707             fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
1708             addInstr(env, PPCInstr_Dfp64Cmp(r_ccPPC, fr_srcL, fr_srcR));
1709 
1710          } else {    //  e->Iex.Binop.op == Iop_CmpD128
1711             iselDfp128Expr(&fr_srcL, &fr_srcL_lo, env, e->Iex.Binop.arg1,
1712                            IEndianess);
1713             iselDfp128Expr(&fr_srcR, &fr_srcR_lo, env, e->Iex.Binop.arg2,
1714                            IEndianess);
1715             addInstr(env, PPCInstr_Dfp128Cmp(r_ccPPC, fr_srcL, fr_srcL_lo,
1716                                              fr_srcR, fr_srcR_lo));
1717          }
1718 
1719          /* Map compare result from PPC to IR,
1720             conforming to CmpF64 definition. */
1721          /*
1722            FP cmp result | PPC | IR
1723            --------------------------
1724            UN            | 0x1 | 0x45
1725            EQ            | 0x2 | 0x40
1726            GT            | 0x4 | 0x00
1727            LT            | 0x8 | 0x01
1728          */
1729 
1730          // r_ccIR_b0 = r_ccPPC[0] | r_ccPPC[3]
1731          addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1732                                      r_ccIR_b0, r_ccPPC,
1733                                      PPCRH_Imm(False,0x3)));
1734          addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b0,
1735                                     r_ccPPC,   PPCRH_Reg(r_ccIR_b0)));
1736          addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b0,
1737                                     r_ccIR_b0, PPCRH_Imm(False,0x1)));
1738 
1739          // r_ccIR_b2 = r_ccPPC[0]
1740          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1741                                      r_ccIR_b2, r_ccPPC,
1742                                      PPCRH_Imm(False,0x2)));
1743          addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b2,
1744                                     r_ccIR_b2, PPCRH_Imm(False,0x4)));
1745 
1746          // r_ccIR_b6 = r_ccPPC[0] | r_ccPPC[1]
1747          addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1748                                      r_ccIR_b6, r_ccPPC,
1749                                      PPCRH_Imm(False,0x1)));
1750          addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b6,
1751                                     r_ccPPC, PPCRH_Reg(r_ccIR_b6)));
1752          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1753                                      r_ccIR_b6, r_ccIR_b6,
1754                                      PPCRH_Imm(False,0x6)));
1755          addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b6,
1756                                     r_ccIR_b6, PPCRH_Imm(False,0x40)));
1757 
1758          // r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6
1759          addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1760                                     r_ccIR_b0, PPCRH_Reg(r_ccIR_b2)));
1761          addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1762                                     r_ccIR,    PPCRH_Reg(r_ccIR_b6)));
1763          return r_ccIR;
1764       }
1765 
1766       if ( e->Iex.Binop.op == Iop_F64toI32S ||
1767                e->Iex.Binop.op == Iop_F64toI32U ) {
1768          /* This works in both mode64 and mode32. */
1769          HReg      r1      = StackFramePtr(env->mode64);
1770          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1771          HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
1772          HReg      ftmp    = newVRegF(env);
1773          HReg      idst    = newVRegI(env);
1774 
1775          /* Set host rounding mode */
1776          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
1777 
1778          sub_from_sp( env, 16 );
1779          addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/,
1780                                        e->Iex.Binop.op == Iop_F64toI32S ? True/*syned*/
1781                                                                      : False,
1782                                        True/*flt64*/,
1783                                        ftmp, fsrc));
1784          addInstr(env, PPCInstr_FpSTFIW(r1, ftmp));
1785          addInstr(env, PPCInstr_Load(4, idst, zero_r1, mode64));
1786 
1787          /* in 64-bit mode we need to sign-widen idst. */
1788          if (mode64)
1789             addInstr(env, PPCInstr_Unary(Pun_EXTSW, idst, idst));
1790 
1791          add_to_sp( env, 16 );
1792 
1793          ///* Restore default FPU rounding. */
1794          //set_FPU_rounding_default( env );
1795          return idst;
1796       }
1797 
1798       if (e->Iex.Binop.op == Iop_F64toI64S || e->Iex.Binop.op == Iop_F64toI64U ) {
1799          if (mode64) {
1800             HReg      r1      = StackFramePtr(env->mode64);
1801             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1802             HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2,
1803                                             IEndianess);
1804             HReg      idst    = newVRegI(env);
1805             HReg      ftmp    = newVRegF(env);
1806 
1807             /* Set host rounding mode */
1808             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
1809 
1810             sub_from_sp( env, 16 );
1811             addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
1812                                           ( e->Iex.Binop.op == Iop_F64toI64S ) ? True
1813                                                                             : False,
1814                                           True, ftmp, fsrc));
1815             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1816             addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
1817             add_to_sp( env, 16 );
1818 
1819             ///* Restore default FPU rounding. */
1820             //set_FPU_rounding_default( env );
1821             return idst;
1822          }
1823       }
1824 
1825       if (e->Iex.Binop.op == Iop_D64toI64S ) {
1826          HReg      r1      = StackFramePtr(env->mode64);
1827          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1828          HReg      fr_src  = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
1829          HReg      idst    = newVRegI(env);
1830          HReg      ftmp    = newVRegF(env);
1831 
1832          /* Set host rounding mode */
1833          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
1834          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTFIX, ftmp, fr_src));
1835          sub_from_sp( env, 16 );
1836          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1837          addInstr(env, PPCInstr_Load(8, idst, zero_r1, mode64));
1838 
1839          add_to_sp( env, 16 );
1840 
1841          ///* Restore default FPU rounding. */
1842          //set_FPU_rounding_default( env );
1843          return idst;
1844       }
1845 
1846       if (e->Iex.Binop.op == Iop_D128toI64S ) {
1847          PPCFpOp fpop = Pfp_DCTFIXQ;
1848          HReg r_srcHi = newVRegF(env);
1849          HReg r_srcLo = newVRegF(env);
1850          HReg idst    = newVRegI(env);
1851          HReg ftmp    = newVRegF(env);
1852          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
1853 
1854          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
1855          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
1856                         IEndianess);
1857          addInstr(env, PPCInstr_DfpD128toD64(fpop, ftmp, r_srcHi, r_srcLo));
1858 
1859          // put the D64 result into an integer register
1860          sub_from_sp( env, 16 );
1861          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1862          addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
1863          add_to_sp( env, 16 );
1864          return idst;
1865       }
1866       break;
1867    }
1868 
1869    /* --------- UNARY OP --------- */
1870    case Iex_Unop: {
1871       IROp op_unop = e->Iex.Unop.op;
1872 
1873       /* 1Uto8(32to1(expr32)) */
1874       DEFINE_PATTERN(p_32to1_then_1Uto8,
1875                      unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
1876       if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
1877          const IRExpr* expr32 = mi.bindee[0];
1878          HReg r_dst = newVRegI(env);
1879          HReg r_src = iselWordExpr_R(env, expr32, IEndianess);
1880          addInstr(env, PPCInstr_Alu(Palu_AND, r_dst,
1881                                     r_src, PPCRH_Imm(False,1)));
1882          return r_dst;
1883       }
1884 
1885       /* 16Uto32(LDbe:I16(expr32)) */
1886       {
1887          DECLARE_PATTERN(p_LDbe16_then_16Uto32);
1888          DEFINE_PATTERN(p_LDbe16_then_16Uto32,
1889                         unop(Iop_16Uto32,
1890                              IRExpr_Load(IEndianess,Ity_I16,bind(0))) );
1891          if (matchIRExpr(&mi,p_LDbe16_then_16Uto32,e)) {
1892             HReg r_dst = newVRegI(env);
1893             PPCAMode* amode
1894                = iselWordExpr_AMode( env, mi.bindee[0], Ity_I16/*xfer*/,
1895                                      IEndianess );
1896             addInstr(env, PPCInstr_Load(2,r_dst,amode, mode64));
1897             return r_dst;
1898          }
1899       }
1900 
1901       switch (op_unop) {
1902       case Iop_8Uto16:
1903       case Iop_8Uto32:
1904       case Iop_8Uto64:
1905       case Iop_16Uto32:
1906       case Iop_16Uto64: {
1907          HReg   r_dst = newVRegI(env);
1908          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1909          UShort mask  = toUShort(op_unop==Iop_16Uto64 ? 0xFFFF :
1910                                  op_unop==Iop_16Uto32 ? 0xFFFF : 0xFF);
1911          addInstr(env, PPCInstr_Alu(Palu_AND,r_dst,r_src,
1912                                     PPCRH_Imm(False,mask)));
1913          return r_dst;
1914       }
1915       case Iop_32Uto64: {
1916          HReg r_dst = newVRegI(env);
1917          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1918          vassert(mode64);
1919          addInstr(env,
1920                   PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1921                                 r_dst, r_src, PPCRH_Imm(False,32)));
1922          addInstr(env,
1923                   PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1924                                 r_dst, r_dst, PPCRH_Imm(False,32)));
1925          return r_dst;
1926       }
1927       case Iop_8Sto16:
1928       case Iop_8Sto32:
1929       case Iop_16Sto32: {
1930          HReg   r_dst = newVRegI(env);
1931          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1932          UShort amt   = toUShort(op_unop==Iop_16Sto32 ? 16 : 24);
1933          addInstr(env,
1934                   PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1935                                 r_dst, r_src, PPCRH_Imm(False,amt)));
1936          addInstr(env,
1937                   PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1938                                 r_dst, r_dst, PPCRH_Imm(False,amt)));
1939          return r_dst;
1940       }
1941       case Iop_8Sto64:
1942       case Iop_16Sto64: {
1943          HReg   r_dst = newVRegI(env);
1944          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1945          UShort amt   = toUShort(op_unop==Iop_8Sto64  ? 56 : 48);
1946          vassert(mode64);
1947          addInstr(env,
1948                   PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1949                                 r_dst, r_src, PPCRH_Imm(False,amt)));
1950          addInstr(env,
1951                   PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
1952                                 r_dst, r_dst, PPCRH_Imm(False,amt)));
1953          return r_dst;
1954       }
1955       case Iop_32Sto64: {
1956          HReg   r_dst = newVRegI(env);
1957          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1958 	 vassert(mode64);
1959          /* According to the IBM docs, in 64 bit mode, srawi r,r,0
1960             sign extends the lower 32 bits into the upper 32 bits. */
1961          addInstr(env,
1962                   PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1963                                 r_dst, r_src, PPCRH_Imm(False,0)));
1964          return r_dst;
1965       }
1966       case Iop_Not8:
1967       case Iop_Not16:
1968       case Iop_Not32:
1969       case Iop_Not64: {
1970          if (op_unop == Iop_Not64) vassert(mode64);
1971          HReg r_dst = newVRegI(env);
1972          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1973          addInstr(env, PPCInstr_Unary(Pun_NOT,r_dst,r_src));
1974          return r_dst;
1975       }
1976       case Iop_64HIto32: {
1977          if (!mode64) {
1978             HReg rHi, rLo;
1979             iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg, IEndianess);
1980             return rHi; /* and abandon rLo .. poor wee thing :-) */
1981          } else {
1982             HReg   r_dst = newVRegI(env);
1983             HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1984             addInstr(env,
1985                      PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1986                                    r_dst, r_src, PPCRH_Imm(False,32)));
1987             return r_dst;
1988          }
1989       }
1990       case Iop_64to32: {
1991          if (!mode64) {
1992             HReg rHi, rLo;
1993             iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg, IEndianess);
1994             return rLo; /* similar stupid comment to the above ... */
1995          } else {
1996             /* This is a no-op. */
1997             return iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
1998          }
1999       }
2000       case Iop_64to16: {
2001          if (mode64) { /* This is a no-op. */
2002             return iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2003          }
2004          break; /* evidently not used in 32-bit mode */
2005       }
2006       case Iop_16HIto8:
2007       case Iop_32HIto16: {
2008          HReg   r_dst = newVRegI(env);
2009          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2010          UShort shift = toUShort(op_unop == Iop_16HIto8 ? 8 : 16);
2011          addInstr(env,
2012                   PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
2013                                 r_dst, r_src, PPCRH_Imm(False,shift)));
2014          return r_dst;
2015       }
2016       case Iop_128HIto64:
2017          if (mode64) {
2018             HReg rHi, rLo;
2019             iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg, IEndianess);
2020             return rHi; /* and abandon rLo .. poor wee thing :-) */
2021          }
2022          break;
2023       case Iop_128to64:
2024          if (mode64) {
2025             HReg rHi, rLo;
2026             iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg, IEndianess);
2027             return rLo; /* similar stupid comment to the above ... */
2028          }
2029          break;
2030       case Iop_1Uto64:
2031       case Iop_1Uto32:
2032       case Iop_1Uto8:
2033          if ((op_unop != Iop_1Uto64) || mode64) {
2034             HReg        r_dst = newVRegI(env);
2035             PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
2036             addInstr(env, PPCInstr_Set(cond,r_dst));
2037             return r_dst;
2038          }
2039          break;
2040       case Iop_1Sto8:
2041       case Iop_1Sto16:
2042       case Iop_1Sto32: {
2043          /* could do better than this, but for now ... */
2044          HReg        r_dst = newVRegI(env);
2045          PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
2046          addInstr(env, PPCInstr_Set(cond,r_dst));
2047          addInstr(env,
2048                   PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
2049                                 r_dst, r_dst, PPCRH_Imm(False,31)));
2050          addInstr(env,
2051                   PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
2052                                 r_dst, r_dst, PPCRH_Imm(False,31)));
2053          return r_dst;
2054       }
2055       case Iop_1Sto64:
2056          if (mode64) {
2057             /* could do better than this, but for now ... */
2058             HReg        r_dst = newVRegI(env);
2059             PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
2060             addInstr(env, PPCInstr_Set(cond,r_dst));
2061             addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
2062                                         r_dst, r_dst, PPCRH_Imm(False,63)));
2063             addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
2064                                         r_dst, r_dst, PPCRH_Imm(False,63)));
2065             return r_dst;
2066          }
2067          break;
2068       case Iop_Clz32:
2069       case Iop_Clz64: {
2070          HReg r_src, r_dst;
2071          PPCUnaryOp op_clz = (op_unop == Iop_Clz32) ? Pun_CLZ32 :
2072                                                       Pun_CLZ64;
2073          if (op_unop == Iop_Clz64 && !mode64)
2074             goto irreducible;
2075          /* Count leading zeroes. */
2076          r_dst = newVRegI(env);
2077          r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2078          addInstr(env, PPCInstr_Unary(op_clz,r_dst,r_src));
2079          return r_dst;
2080       }
2081 
2082       case Iop_Ctz32:
2083       case Iop_Ctz64: {
2084          HReg r_src, r_dst;
2085          PPCUnaryOp op_clz = (op_unop == Iop_Ctz32) ? Pun_CTZ32 :
2086                                                       Pun_CTZ64;
2087          if (op_unop == Iop_Ctz64 && !mode64)
2088             goto irreducible;
2089          /* Count trailing zeroes. */
2090          r_dst = newVRegI(env);
2091          r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2092          addInstr(env, PPCInstr_Unary(op_clz,r_dst,r_src));
2093          return r_dst;
2094       }
2095 
2096       case Iop_Left8:
2097       case Iop_Left16:
2098       case Iop_Left32:
2099       case Iop_Left64: {
2100          HReg r_src, r_dst;
2101          if (op_unop == Iop_Left64 && !mode64)
2102             goto irreducible;
2103          r_dst = newVRegI(env);
2104          r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2105          addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
2106          addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
2107          return r_dst;
2108       }
2109 
2110       case Iop_CmpwNEZ32: {
2111          HReg r_dst = newVRegI(env);
2112          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2113          addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
2114          addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
2115          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
2116                                      r_dst, r_dst, PPCRH_Imm(False, 31)));
2117          return r_dst;
2118       }
2119 
2120       case Iop_CmpwNEZ64: {
2121          HReg r_dst = newVRegI(env);
2122          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2123          if (!mode64) goto irreducible;
2124          addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
2125          addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
2126          addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
2127                                      r_dst, r_dst, PPCRH_Imm(False, 63)));
2128          return r_dst;
2129       }
2130 
2131       case Iop_V128to32: {
2132          HReg        r_aligned16;
2133          HReg        dst  = newVRegI(env);
2134          HReg        vec  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
2135          PPCAMode *am_off0, *am_off_word0;
2136          sub_from_sp( env, 32 );     // Move SP down 32 bytes
2137 
2138          // get a quadword aligned address within our stack space
2139          r_aligned16 = get_sp_aligned16( env );
2140          am_off0  = PPCAMode_IR( 0, r_aligned16 );
2141 
2142          /* Note that the store below (done via PPCInstr_AvLdSt) uses
2143           * stvx, which stores the vector in proper LE format,
2144           * with byte zero (far right byte of the register in LE format)
2145           * stored at the lowest memory address.  Therefore, to obtain
2146           * integer word zero, we need to use that lowest memory address
2147           * as the base for the load.
2148           */
2149          if (IEndianess == Iend_LE)
2150             am_off_word0 = am_off0;
2151          else
2152             am_off_word0 = PPCAMode_IR( 12,r_aligned16 );
2153 
2154          // store vec, load low word to dst
2155          addInstr(env,
2156                   PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
2157          addInstr(env,
2158                   PPCInstr_Load( 4, dst, am_off_word0, mode64 ));
2159 
2160          add_to_sp( env, 32 );       // Reset SP
2161          return dst;
2162       }
2163 
2164       case Iop_V128to64:
2165       case Iop_V128HIto64:
2166          if (mode64) {
2167             HReg     r_aligned16;
2168             HReg     dst = newVRegI(env);
2169             HReg     vec = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
2170             PPCAMode *am_off0, *am_off8, *am_off_arg;
2171             sub_from_sp( env, 32 );     // Move SP down 32 bytes
2172 
2173             // get a quadword aligned address within our stack space
2174             r_aligned16 = get_sp_aligned16( env );
2175             am_off0 = PPCAMode_IR( 0, r_aligned16 );
2176             am_off8 = PPCAMode_IR( 8 ,r_aligned16 );
2177 
2178             // store vec, load low word or high to dst
2179             addInstr(env,
2180                      PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
2181             if (IEndianess == Iend_LE) {
2182                if (op_unop == Iop_V128HIto64)
2183                   am_off_arg = am_off8;
2184                else
2185                   am_off_arg = am_off0;
2186             } else {
2187                if (op_unop == Iop_V128HIto64)
2188                   am_off_arg = am_off0;
2189                else
2190                   am_off_arg = am_off8;
2191             }
2192             addInstr(env,
2193                      PPCInstr_Load(
2194                         8, dst,
2195                         am_off_arg,
2196                         mode64 ));
2197 
2198             add_to_sp( env, 32 );       // Reset SP
2199             return dst;
2200          }
2201          break;
2202       case Iop_16to8:
2203       case Iop_32to8:
2204       case Iop_32to16:
2205       case Iop_64to8:
2206          /* These are no-ops. */
2207          return iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2208 
2209       /* ReinterpF64asI64(e) */
2210       /* Given an IEEE754 double, produce an I64 with the same bit
2211          pattern. */
2212       case Iop_ReinterpF64asI64:
2213          if (mode64) {
2214             PPCAMode *am_addr;
2215             HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
2216             HReg r_dst  = newVRegI(env);
2217 
2218             sub_from_sp( env, 16 );     // Move SP down 16 bytes
2219             am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
2220 
2221             // store as F64
2222             addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
2223                                            fr_src, am_addr ));
2224             // load as Ity_I64
2225             addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
2226 
2227             add_to_sp( env, 16 );       // Reset SP
2228             return r_dst;
2229          }
2230          break;
2231 
2232       /* ReinterpF32asI32(e) */
2233       /* Given an IEEE754 float, produce an I32 with the same bit
2234          pattern. */
2235       case Iop_ReinterpF32asI32: {
2236          /* I believe this generates correct code for both 32- and
2237             64-bit hosts. */
2238          PPCAMode *am_addr;
2239          HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg, IEndianess);
2240          HReg r_dst  = newVRegI(env);
2241 
2242          sub_from_sp( env, 16 );     // Move SP down 16 bytes
2243          am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
2244 
2245          // store as F32
2246          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
2247                                         fr_src, am_addr ));
2248          // load as Ity_I32
2249          addInstr(env, PPCInstr_Load( 4, r_dst, am_addr, mode64 ));
2250 
2251          add_to_sp( env, 16 );       // Reset SP
2252          return r_dst;
2253       }
2254       break;
2255 
2256       case Iop_ReinterpD64asI64:
2257          if (mode64) {
2258             PPCAMode *am_addr;
2259             HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
2260             HReg r_dst  = newVRegI(env);
2261 
2262             sub_from_sp( env, 16 );     // Move SP down 16 bytes
2263             am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
2264 
2265             // store as D64
2266             addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
2267                                            fr_src, am_addr ));
2268             // load as Ity_I64
2269             addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
2270             add_to_sp( env, 16 );       // Reset SP
2271             return r_dst;
2272          }
2273          break;
2274 
2275       case Iop_BCDtoDPB: {
2276          /* the following is only valid in 64 bit mode */
2277          if (!mode64) break;
2278 
2279          PPCCondCode cc;
2280          UInt        argiregs;
2281          HReg        argregs[1];
2282          HReg        r_dst  = newVRegI(env);
2283          Int         argreg;
2284 
2285          argiregs = 0;
2286          argreg = 0;
2287          argregs[0] = hregPPC_GPR3(mode64);
2288 
2289          argiregs |= (1 << (argreg+3));
2290          addInstr(env, mk_iMOVds_RR( argregs[argreg++],
2291                                      iselWordExpr_R(env, e->Iex.Unop.arg,
2292                                                     IEndianess) ) );
2293 
2294          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
2295          if (IEndianess == Iend_LE) {
2296              addInstr(env, PPCInstr_Call( cc, (Addr)h_calc_BCDtoDPB,
2297                                           argiregs,
2298                                           mk_RetLoc_simple(RLPri_Int)) );
2299          } else {
2300              HWord*      fdescr;
2301              fdescr = (HWord*)h_calc_BCDtoDPB;
2302              addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]),
2303                                           argiregs,
2304                                           mk_RetLoc_simple(RLPri_Int)) );
2305          }
2306 
2307          addInstr(env, mk_iMOVds_RR(r_dst, argregs[0]));
2308          return r_dst;
2309       }
2310 
2311       case Iop_DPBtoBCD: {
2312          /* the following is only valid in 64 bit mode */
2313          if (!mode64) break;
2314 
2315          PPCCondCode cc;
2316          UInt        argiregs;
2317          HReg        argregs[1];
2318          HReg        r_dst  = newVRegI(env);
2319          Int         argreg;
2320 
2321          argiregs = 0;
2322          argreg = 0;
2323          argregs[0] = hregPPC_GPR3(mode64);
2324 
2325          argiregs |= (1 << (argreg+3));
2326          addInstr(env, mk_iMOVds_RR( argregs[argreg++],
2327                                      iselWordExpr_R(env, e->Iex.Unop.arg,
2328                                                     IEndianess) ) );
2329 
2330          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
2331 
2332         if (IEndianess == Iend_LE) {
2333             addInstr(env, PPCInstr_Call( cc, (Addr)h_calc_DPBtoBCD,
2334                                          argiregs,
2335                                          mk_RetLoc_simple(RLPri_Int) ) );
2336         } else {
2337             HWord*      fdescr;
2338             fdescr = (HWord*)h_calc_DPBtoBCD;
2339             addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]),
2340                                          argiregs,
2341                                          mk_RetLoc_simple(RLPri_Int) ) );
2342          }
2343 
2344          addInstr(env, mk_iMOVds_RR(r_dst, argregs[0]));
2345          return r_dst;
2346       }
2347       case Iop_F32toF16x4: {
2348          HReg vdst = newVRegV(env);    /* V128 */
2349          HReg dst  = newVRegI(env);    /* I64*/
2350          HReg r0 = newVRegI(env);    /* I16*/
2351          HReg r1 = newVRegI(env);    /* I16*/
2352          HReg r2 = newVRegI(env);    /* I16*/
2353          HReg r3 = newVRegI(env);    /* I16*/
2354          HReg vsrc  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
2355          PPCAMode *am_off0, *am_off2, *am_off4, *am_off6, *am_off8;
2356          PPCAMode *am_off10, *am_off12, *am_off14;
2357          HReg r_aligned16;
2358 
2359          sub_from_sp( env, 32 );     // Move SP down
2360 
2361          /* issue instruction */
2362          addInstr(env, PPCInstr_AvUnary(Pav_F32toF16x4, vdst, vsrc));
2363 
2364          /* Get a  quadword aligned address within our stack space */
2365          r_aligned16 = get_sp_aligned16( env );
2366          am_off0  = PPCAMode_IR( 0, r_aligned16 );
2367          am_off2  = PPCAMode_IR( 2, r_aligned16 );
2368          am_off4  = PPCAMode_IR( 4, r_aligned16 );
2369          am_off6  = PPCAMode_IR( 6, r_aligned16 );
2370          am_off8  = PPCAMode_IR( 8, r_aligned16 );
2371          am_off10 = PPCAMode_IR( 10, r_aligned16 );
2372          am_off12 = PPCAMode_IR( 12, r_aligned16 );
2373          am_off14 = PPCAMode_IR( 14, r_aligned16 );
2374 
2375          /* Store v128 result to stack. */
2376          addInstr(env, PPCInstr_AvLdSt(False/*store*/, 16, vdst, am_off0));
2377 
2378          /* fetch four I16 from V128, store into contiguous I64 via stack,  */
2379          if (IEndianess == Iend_LE) {
2380             addInstr(env, PPCInstr_Load( 2, r3, am_off12, mode64));
2381             addInstr(env, PPCInstr_Load( 2, r2, am_off8, mode64));
2382             addInstr(env, PPCInstr_Load( 2, r1, am_off4, mode64));
2383             addInstr(env, PPCInstr_Load( 2, r0, am_off0, mode64));
2384          } else {
2385             addInstr(env, PPCInstr_Load( 2, r0, am_off14, mode64));
2386             addInstr(env, PPCInstr_Load( 2, r1, am_off10, mode64));
2387             addInstr(env, PPCInstr_Load( 2, r2, am_off6, mode64));
2388             addInstr(env, PPCInstr_Load( 2, r3, am_off2, mode64));
2389          }
2390 
2391          /* store in contiguous 64-bit values */
2392          addInstr(env, PPCInstr_Store( 2, am_off6, r3, mode64));
2393          addInstr(env, PPCInstr_Store( 2, am_off4, r2, mode64));
2394          addInstr(env, PPCInstr_Store( 2, am_off2, r1, mode64));
2395          addInstr(env, PPCInstr_Store( 2, am_off0, r0, mode64));
2396 
2397          /* Fetch I64 */
2398          addInstr(env, PPCInstr_Load(8, dst, am_off0, mode64));
2399 
2400          add_to_sp( env, 32 );          // Reset SP
2401          return dst;
2402       }
2403 
2404       default:
2405          break;
2406       }
2407 
2408      switch (e->Iex.Unop.op) {
2409         case Iop_ExtractExpD64: {
2410 
2411             HReg fr_dst = newVRegI(env);
2412             HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
2413             HReg tmp    = newVRegF(env);
2414             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
2415             addInstr(env, PPCInstr_Dfp64Unary(Pfp_DXEX, tmp, fr_src));
2416 
2417             // put the D64 result into a integer register
2418             sub_from_sp( env, 16 );
2419             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
2420             addInstr(env, PPCInstr_Load(8, fr_dst, zero_r1, env->mode64));
2421             add_to_sp( env, 16 );
2422             return fr_dst;
2423          }
2424          case Iop_ExtractExpD128: {
2425             HReg fr_dst = newVRegI(env);
2426             HReg r_srcHi;
2427             HReg r_srcLo;
2428             HReg tmp    = newVRegF(env);
2429             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
2430 
2431             iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Unop.arg,
2432                            IEndianess);
2433             addInstr(env, PPCInstr_ExtractExpD128(Pfp_DXEXQ, tmp,
2434                                                   r_srcHi, r_srcLo));
2435 
2436             sub_from_sp( env, 16 );
2437             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
2438             addInstr(env, PPCInstr_Load(8, fr_dst, zero_r1, env->mode64));
2439             add_to_sp( env, 16 );
2440             return fr_dst;
2441          }
2442          default:
2443             break;
2444       }
2445 
2446       break;
2447    }
2448 
2449    /* --------- GET --------- */
2450    case Iex_Get: {
2451       if (ty == Ity_I8  || ty == Ity_I16 ||
2452           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
2453          HReg r_dst = newVRegI(env);
2454          PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
2455                                           GuestStatePtr(mode64) );
2456          addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
2457                                       r_dst, am_addr, mode64 ));
2458          return r_dst;
2459       }
2460       break;
2461    }
2462 
2463    case Iex_GetI: {
2464       PPCAMode* src_am
2465          = genGuestArrayOffset( env, e->Iex.GetI.descr,
2466                                 e->Iex.GetI.ix, e->Iex.GetI.bias,
2467                                 IEndianess );
2468       HReg r_dst = newVRegI(env);
2469       if (mode64 && ty == Ity_I64) {
2470          addInstr(env, PPCInstr_Load( toUChar(8),
2471                                       r_dst, src_am, mode64 ));
2472          return r_dst;
2473       }
2474       if ((!mode64) && ty == Ity_I32) {
2475          addInstr(env, PPCInstr_Load( toUChar(4),
2476                                       r_dst, src_am, mode64 ));
2477          return r_dst;
2478       }
2479       break;
2480    }
2481 
2482    /* --------- CCALL --------- */
2483    case Iex_CCall: {
2484       vassert(ty == e->Iex.CCall.retty); /* well-formedness of IR */
2485 
2486       /* be very restrictive for now.  Only 32/64-bit ints allowed for
2487          args, and 32 bits or host machine word for return type. */
2488       if (!(ty == Ity_I32 || (mode64 && ty == Ity_I64)))
2489          goto irreducible;
2490 
2491       /* Marshal args, do the call, clear stack. */
2492       UInt   addToSp = 0;
2493       RetLoc rloc    = mk_RetLoc_INVALID();
2494       doHelperCall( &addToSp, &rloc, env, NULL/*guard*/,
2495                     e->Iex.CCall.cee, e->Iex.CCall.retty, e->Iex.CCall.args,
2496                     IEndianess );
2497       vassert(is_sane_RetLoc(rloc));
2498       vassert(rloc.pri == RLPri_Int);
2499       vassert(addToSp == 0);
2500 
2501       /* GPR3 now holds the destination address from Pin_Goto */
2502       HReg r_dst = newVRegI(env);
2503       addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
2504       return r_dst;
2505    }
2506 
2507    /* --------- LITERAL --------- */
2508    /* 32/16/8-bit literals */
2509    case Iex_Const: {
2510       Long l;
2511       HReg r_dst = newVRegI(env);
2512       IRConst* con = e->Iex.Const.con;
2513       switch (con->tag) {
2514          case Ico_U64: if (!mode64) goto irreducible;
2515                        l = (Long)            con->Ico.U64; break;
2516          case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
2517          case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
2518          case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
2519          default:      vpanic("iselIntExpr_R.const(ppc)");
2520       }
2521       addInstr(env, PPCInstr_LI(r_dst, (ULong)l, mode64));
2522       return r_dst;
2523    }
2524 
2525    /* --------- MULTIPLEX --------- */
2526    case Iex_ITE: { // VFD
2527       if ((ty == Ity_I8  || ty == Ity_I16 ||
2528            ty == Ity_I32 || ((ty == Ity_I64) && mode64)) &&
2529           typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) {
2530          PPCRI* r1    = iselWordExpr_RI(env, e->Iex.ITE.iftrue, IEndianess);
2531          HReg   r0    = iselWordExpr_R(env, e->Iex.ITE.iffalse, IEndianess);
2532          HReg   r_dst = newVRegI(env);
2533          addInstr(env, mk_iMOVds_RR(r_dst,r0));
2534          PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond, IEndianess);
2535          addInstr(env, PPCInstr_CMov(cc, r_dst, r1));
2536          return r_dst;
2537       }
2538       break;
2539    }
2540 
2541    default:
2542       break;
2543    } /* switch (e->tag) */
2544 
2545 
2546    /* We get here if no pattern matched. */
2547  irreducible:
2548    ppIRExpr(e);
2549    vpanic("iselIntExpr_R(ppc): cannot reduce tree");
2550 }
2551 
2552 
2553 /*---------------------------------------------------------*/
2554 /*--- ISEL: Integer expression auxiliaries              ---*/
2555 /*---------------------------------------------------------*/
2556 
2557 /* --------------------- AMODEs --------------------- */
2558 
2559 /* Return an AMode which computes the value of the specified
2560    expression, possibly also adding insns to the code list as a
2561    result.  The expression may only be a word-size one.
2562 */
2563 
uInt_fits_in_16_bits(UInt u)2564 static Bool uInt_fits_in_16_bits ( UInt u )
2565 {
2566    /* Is u the same as the sign-extend of its lower 16 bits? */
2567    UInt v = u & 0xFFFF;
2568 
2569    v = (Int)(v << 16) >> 16;   /* sign extend */
2570 
2571    return u == v;
2572 }
2573 
uLong_fits_in_16_bits(ULong u)2574 static Bool uLong_fits_in_16_bits ( ULong u )
2575 {
2576    /* Is u the same as the sign-extend of its lower 16 bits? */
2577    ULong v = u & 0xFFFFULL;
2578 
2579    v = (Long)(v << 48) >> 48;   /* sign extend */
2580 
2581    return u == v;
2582 }
2583 
uLong_is_4_aligned(ULong u)2584 static Bool uLong_is_4_aligned ( ULong u )
2585 {
2586    return toBool((u & 3ULL) == 0);
2587 }
2588 
sane_AMode(ISelEnv * env,PPCAMode * am)2589 static Bool sane_AMode ( ISelEnv* env, PPCAMode* am )
2590 {
2591    Bool mode64 = env->mode64;
2592    switch (am->tag) {
2593    case Pam_IR:
2594       /* Using uInt_fits_in_16_bits in 64-bit mode seems a bit bogus,
2595          somehow, but I think it's OK. */
2596       return toBool( hregClass(am->Pam.IR.base) == HRcGPR(mode64) &&
2597                      hregIsVirtual(am->Pam.IR.base) &&
2598                      uInt_fits_in_16_bits(am->Pam.IR.index) );
2599    case Pam_RR:
2600       return toBool( hregClass(am->Pam.RR.base) == HRcGPR(mode64) &&
2601                      hregIsVirtual(am->Pam.RR.base) &&
2602                      hregClass(am->Pam.RR.index) == HRcGPR(mode64) &&
2603                      hregIsVirtual(am->Pam.RR.index) );
2604    default:
2605       vpanic("sane_AMode: unknown ppc amode tag");
2606    }
2607 }
2608 
2609 static
iselWordExpr_AMode(ISelEnv * env,const IRExpr * e,IRType xferTy,IREndness IEndianess)2610 PPCAMode* iselWordExpr_AMode ( ISelEnv* env, const IRExpr* e, IRType xferTy,
2611                                IREndness IEndianess )
2612 {
2613    PPCAMode* am = iselWordExpr_AMode_wrk(env, e, xferTy, IEndianess);
2614    vassert(sane_AMode(env, am));
2615    return am;
2616 }
2617 
2618 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_AMode_wrk(ISelEnv * env,const IRExpr * e,IRType xferTy,IREndness IEndianess)2619 static PPCAMode* iselWordExpr_AMode_wrk ( ISelEnv* env, const IRExpr* e,
2620                                           IRType xferTy, IREndness IEndianess )
2621 {
2622    IRType ty = typeOfIRExpr(env->type_env,e);
2623 
2624    if (env->mode64) {
2625 
2626       /* If the data load/store type is I32 or I64, this amode might
2627          be destined for use in ld/ldu/lwa/st/stu.  In which case
2628          insist that if it comes out as an _IR, the immediate must
2629          have its bottom two bits be zero.  This does assume that for
2630          any other type (I8/I16/I128/F32/F64/V128) the amode will not
2631          be parked in any such instruction.  But that seems a
2632          reasonable assumption.  */
2633       Bool aligned4imm = toBool(xferTy == Ity_I32 || xferTy == Ity_I64);
2634 
2635       vassert(ty == Ity_I64);
2636 
2637       /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
2638       if (e->tag == Iex_Binop
2639           && e->Iex.Binop.op == Iop_Add64
2640           && e->Iex.Binop.arg2->tag == Iex_Const
2641           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
2642           && (aligned4imm  ? uLong_is_4_aligned(e->Iex.Binop.arg2
2643                                                  ->Iex.Const.con->Ico.U64)
2644                            : True)
2645           && uLong_fits_in_16_bits(e->Iex.Binop.arg2
2646                                     ->Iex.Const.con->Ico.U64)) {
2647          return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
2648                              iselWordExpr_R(env, e->Iex.Binop.arg1,
2649                                             IEndianess) );
2650       }
2651 
2652       /* Add64(expr,expr) */
2653       if (e->tag == Iex_Binop
2654           && e->Iex.Binop.op == Iop_Add64) {
2655          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
2656          HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
2657          return PPCAMode_RR( r_idx, r_base );
2658       }
2659 
2660    } else {
2661 
2662       vassert(ty == Ity_I32);
2663 
2664       /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
2665       if (e->tag == Iex_Binop
2666           && e->Iex.Binop.op == Iop_Add32
2667           && e->Iex.Binop.arg2->tag == Iex_Const
2668           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
2669           && uInt_fits_in_16_bits(e->Iex.Binop.arg2
2670                                    ->Iex.Const.con->Ico.U32)) {
2671          return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
2672                              iselWordExpr_R(env, e->Iex.Binop.arg1,
2673                                             IEndianess) );
2674       }
2675 
2676       /* Add32(expr,expr) */
2677       if (e->tag == Iex_Binop
2678           && e->Iex.Binop.op == Iop_Add32) {
2679          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
2680          HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
2681          return PPCAMode_RR( r_idx, r_base );
2682       }
2683 
2684    }
2685 
2686    /* Doesn't match anything in particular.  Generate it into
2687       a register and use that. */
2688    return PPCAMode_IR( 0, iselWordExpr_R(env,e,IEndianess) );
2689 }
2690 
2691 
2692 /* --------------------- RH --------------------- */
2693 
2694 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
2695    (reg-or-halfword-immediate).  It's important to specify whether the
2696    immediate is to be regarded as signed or not.  If yes, this will
2697    never return -32768 as an immediate; this guaranteed that all
2698    signed immediates that are return can have their sign inverted if
2699    need be. */
2700 
iselWordExpr_RH(ISelEnv * env,Bool syned,const IRExpr * e,IREndness IEndianess)2701 static PPCRH* iselWordExpr_RH ( ISelEnv* env, Bool syned, const IRExpr* e,
2702                                 IREndness IEndianess )
2703 {
2704   PPCRH* ri = iselWordExpr_RH_wrk(env, syned, e, IEndianess);
2705    /* sanity checks ... */
2706    switch (ri->tag) {
2707    case Prh_Imm:
2708       vassert(ri->Prh.Imm.syned == syned);
2709       if (syned)
2710          vassert(ri->Prh.Imm.imm16 != 0x8000);
2711       return ri;
2712    case Prh_Reg:
2713       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2714       vassert(hregIsVirtual(ri->Prh.Reg.reg));
2715       return ri;
2716    default:
2717       vpanic("iselIntExpr_RH: unknown ppc RH tag");
2718    }
2719 }
2720 
2721 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH_wrk(ISelEnv * env,Bool syned,const IRExpr * e,IREndness IEndianess)2722 static PPCRH* iselWordExpr_RH_wrk ( ISelEnv* env, Bool syned, const IRExpr* e,
2723                                     IREndness IEndianess )
2724 {
2725    ULong u;
2726    Long  l;
2727    IRType ty = typeOfIRExpr(env->type_env,e);
2728    vassert(ty == Ity_I8  || ty == Ity_I16 ||
2729            ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2730 
2731    /* special case: immediate */
2732    if (e->tag == Iex_Const) {
2733       IRConst* con = e->Iex.Const.con;
2734       /* What value are we aiming to generate? */
2735       switch (con->tag) {
2736       /* Note: Not sign-extending - we carry 'syned' around */
2737       case Ico_U64: vassert(env->mode64);
2738                     u =              con->Ico.U64; break;
2739       case Ico_U32: u = 0xFFFFFFFF & con->Ico.U32; break;
2740       case Ico_U16: u = 0x0000FFFF & con->Ico.U16; break;
2741       case Ico_U8:  u = 0x000000FF & con->Ico.U8; break;
2742       default:      vpanic("iselIntExpr_RH.Iex_Const(ppch)");
2743       }
2744       l = (Long)u;
2745       /* Now figure out if it's representable. */
2746       if (!syned && u <= 65535) {
2747          return PPCRH_Imm(False/*unsigned*/, toUShort(u & 0xFFFF));
2748       }
2749       if (syned && l >= -32767 && l <= 32767) {
2750          return PPCRH_Imm(True/*signed*/, toUShort(u & 0xFFFF));
2751       }
2752       /* no luck; use the Slow Way. */
2753    }
2754 
2755    /* default case: calculate into a register and return that */
2756    return PPCRH_Reg( iselWordExpr_R ( env, e, IEndianess ) );
2757 }
2758 
2759 
2760 /* --------------------- RIs --------------------- */
2761 
2762 /* Calculate an expression into an PPCRI operand.  As with
2763    iselIntExpr_R, the expression can have type 32, 16 or 8 bits, or,
2764    in 64-bit mode, 64 bits. */
2765 
iselWordExpr_RI(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2766 static PPCRI* iselWordExpr_RI ( ISelEnv* env, const IRExpr* e,
2767                                 IREndness IEndianess )
2768 {
2769    PPCRI* ri = iselWordExpr_RI_wrk(env, e, IEndianess);
2770    /* sanity checks ... */
2771    switch (ri->tag) {
2772    case Pri_Imm:
2773       return ri;
2774    case Pri_Reg:
2775       vassert(hregClass(ri->Pri.Reg) == HRcGPR(env->mode64));
2776       vassert(hregIsVirtual(ri->Pri.Reg));
2777       return ri;
2778    default:
2779       vpanic("iselIntExpr_RI: unknown ppc RI tag");
2780    }
2781 }
2782 
2783 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RI_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2784 static PPCRI* iselWordExpr_RI_wrk ( ISelEnv* env, const IRExpr* e,
2785                                     IREndness IEndianess )
2786 {
2787    Long  l;
2788    IRType ty = typeOfIRExpr(env->type_env,e);
2789    vassert(ty == Ity_I8  || ty == Ity_I16 ||
2790            ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2791 
2792    /* special case: immediate */
2793    if (e->tag == Iex_Const) {
2794       IRConst* con = e->Iex.Const.con;
2795       switch (con->tag) {
2796       case Ico_U64: vassert(env->mode64);
2797                     l = (Long)            con->Ico.U64; break;
2798       case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
2799       case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
2800       case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
2801       default:      vpanic("iselIntExpr_RI.Iex_Const(ppch)");
2802       }
2803       return PPCRI_Imm((ULong)l);
2804    }
2805 
2806    /* default case: calculate into a register and return that */
2807    return PPCRI_Reg( iselWordExpr_R ( env, e, IEndianess ) );
2808 }
2809 
2810 
2811 /* --------------------- RH5u --------------------- */
2812 
2813 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
2814    being an immediate in the range 1 .. 31 inclusive.  Used for doing
2815    shift amounts.  Only used in 32-bit mode. */
2816 
iselWordExpr_RH5u(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2817 static PPCRH* iselWordExpr_RH5u ( ISelEnv* env, const IRExpr* e,
2818                                   IREndness IEndianess )
2819 {
2820    PPCRH* ri;
2821    vassert(!env->mode64);
2822    ri = iselWordExpr_RH5u_wrk(env, e, IEndianess);
2823    /* sanity checks ... */
2824    switch (ri->tag) {
2825    case Prh_Imm:
2826       vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 31);
2827       vassert(!ri->Prh.Imm.syned);
2828       return ri;
2829    case Prh_Reg:
2830       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2831       vassert(hregIsVirtual(ri->Prh.Reg.reg));
2832       return ri;
2833    default:
2834       vpanic("iselIntExpr_RH5u: unknown ppc RI tag");
2835    }
2836 }
2837 
2838 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH5u_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2839 static PPCRH* iselWordExpr_RH5u_wrk ( ISelEnv* env, const IRExpr* e,
2840                                       IREndness IEndianess )
2841 {
2842    IRType ty = typeOfIRExpr(env->type_env,e);
2843    vassert(ty == Ity_I8);
2844 
2845    /* special case: immediate */
2846    if (e->tag == Iex_Const
2847        && e->Iex.Const.con->tag == Ico_U8
2848        && e->Iex.Const.con->Ico.U8 >= 1
2849        && e->Iex.Const.con->Ico.U8 <= 31) {
2850       return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
2851    }
2852 
2853    /* default case: calculate into a register and return that */
2854    return PPCRH_Reg( iselWordExpr_R ( env, e, IEndianess ) );
2855 }
2856 
2857 
2858 /* --------------------- RH6u --------------------- */
2859 
2860 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter
2861    being an immediate in the range 1 .. 63 inclusive.  Used for doing
2862    shift amounts.  Only used in 64-bit mode. */
2863 
iselWordExpr_RH6u(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2864 static PPCRH* iselWordExpr_RH6u ( ISelEnv* env, const IRExpr* e,
2865                                   IREndness IEndianess )
2866 {
2867    PPCRH* ri;
2868    vassert(env->mode64);
2869    ri = iselWordExpr_RH6u_wrk(env, e, IEndianess);
2870    /* sanity checks ... */
2871    switch (ri->tag) {
2872    case Prh_Imm:
2873       vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 63);
2874       vassert(!ri->Prh.Imm.syned);
2875       return ri;
2876    case Prh_Reg:
2877       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2878       vassert(hregIsVirtual(ri->Prh.Reg.reg));
2879       return ri;
2880    default:
2881       vpanic("iselIntExpr_RH6u: unknown ppc64 RI tag");
2882    }
2883 }
2884 
2885 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH6u_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2886 static PPCRH* iselWordExpr_RH6u_wrk ( ISelEnv* env, const IRExpr* e,
2887                                       IREndness IEndianess )
2888 {
2889    IRType ty = typeOfIRExpr(env->type_env,e);
2890    vassert(ty == Ity_I8);
2891 
2892    /* special case: immediate */
2893    if (e->tag == Iex_Const
2894        && e->Iex.Const.con->tag == Ico_U8
2895        && e->Iex.Const.con->Ico.U8 >= 1
2896        && e->Iex.Const.con->Ico.U8 <= 63) {
2897       return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
2898    }
2899 
2900    /* default case: calculate into a register and return that */
2901    return PPCRH_Reg( iselWordExpr_R ( env, e, IEndianess ) );
2902 }
2903 
2904 
2905 /* --------------------- CONDCODE --------------------- */
2906 
2907 /* Generate code to evaluated a bit-typed expression, returning the
2908    condition code which would correspond when the expression would
2909    notionally have returned 1. */
2910 
iselCondCode(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2911 static PPCCondCode iselCondCode ( ISelEnv* env, const IRExpr* e,
2912                                   IREndness IEndianess )
2913 {
2914    /* Uh, there's nothing we can sanity check here, unfortunately. */
2915    return iselCondCode_wrk(env,e, IEndianess);
2916 }
2917 
2918 /* DO NOT CALL THIS DIRECTLY ! */
iselCondCode_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)2919 static PPCCondCode iselCondCode_wrk ( ISelEnv* env, const IRExpr* e,
2920                                       IREndness IEndianess )
2921 {
2922    vassert(e);
2923    vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
2924 
2925    /* Constant 1:Bit */
2926    if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True) {
2927       // Make a compare that will always be true:
2928       HReg r_zero = newVRegI(env);
2929       addInstr(env, PPCInstr_LI(r_zero, 0, env->mode64));
2930       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2931                                  7/*cr*/, r_zero, PPCRH_Reg(r_zero)));
2932       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2933    }
2934 
2935    /* Not1(...) */
2936    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
2937       /* Generate code for the arg, and negate the test condition */
2938       PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
2939       cond.test = invertCondTest(cond.test);
2940       return cond;
2941    }
2942 
2943    /* --- patterns rooted at: 32to1 or 64to1 --- */
2944 
2945    /* 32to1, 64to1 */
2946    if (e->tag == Iex_Unop &&
2947        (e->Iex.Unop.op == Iop_32to1 || e->Iex.Unop.op == Iop_64to1)) {
2948       HReg src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2949       HReg tmp = newVRegI(env);
2950       /* could do better, probably -- andi. */
2951       addInstr(env, PPCInstr_Alu(Palu_AND, tmp,
2952                                  src, PPCRH_Imm(False,1)));
2953       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2954                                  7/*cr*/, tmp, PPCRH_Imm(False,1)));
2955       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2956    }
2957 
2958    /* --- patterns rooted at: CmpNEZ8 --- */
2959 
2960    /* CmpNEZ8(x) */
2961    /* Note this cloned as CmpNE8(x,0) below. */
2962    /* could do better -- andi. */
2963    if (e->tag == Iex_Unop
2964        && e->Iex.Unop.op == Iop_CmpNEZ8) {
2965       HReg arg = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2966       HReg tmp = newVRegI(env);
2967       addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
2968                                  PPCRH_Imm(False,0xFF)));
2969       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2970                                  7/*cr*/, tmp, PPCRH_Imm(False,0)));
2971       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2972    }
2973 
2974    /* --- patterns rooted at: CmpNEZ32 --- */
2975 
2976    /* CmpNEZ32(x) */
2977    if (e->tag == Iex_Unop
2978        && e->Iex.Unop.op == Iop_CmpNEZ32) {
2979       HReg r1 = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
2980       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2981                                  7/*cr*/, r1, PPCRH_Imm(False,0)));
2982       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2983    }
2984 
2985    /* --- patterns rooted at: Cmp*32* --- */
2986 
2987    /* Cmp*32*(x,y) */
2988    if (e->tag == Iex_Binop
2989        && (e->Iex.Binop.op == Iop_CmpEQ32
2990            || e->Iex.Binop.op == Iop_CmpNE32
2991            || e->Iex.Binop.op == Iop_CmpLT32S
2992            || e->Iex.Binop.op == Iop_CmpLT32U
2993            || e->Iex.Binop.op == Iop_CmpLE32S
2994            || e->Iex.Binop.op == Iop_CmpLE32U)) {
2995       Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S ||
2996                     e->Iex.Binop.op == Iop_CmpLE32S);
2997       HReg   r1  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
2998       PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2, IEndianess);
2999       addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
3000                                  7/*cr*/, r1, ri2));
3001 
3002       switch (e->Iex.Binop.op) {
3003       case Iop_CmpEQ32:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
3004       case Iop_CmpNE32:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3005       case Iop_CmpLT32U: case Iop_CmpLT32S:
3006          return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
3007       case Iop_CmpLE32U: case Iop_CmpLE32S:
3008          return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
3009       default: vpanic("iselCondCode(ppc): CmpXX32");
3010       }
3011    }
3012 
3013    /* --- patterns rooted at: CmpNEZ64 --- */
3014 
3015    /* CmpNEZ64 */
3016    if (e->tag == Iex_Unop
3017        && e->Iex.Unop.op == Iop_CmpNEZ64) {
3018       if (!env->mode64) {
3019          HReg hi, lo;
3020          HReg tmp = newVRegI(env);
3021          iselInt64Expr( &hi, &lo, env, e->Iex.Unop.arg, IEndianess );
3022          addInstr(env, PPCInstr_Alu(Palu_OR, tmp, lo, PPCRH_Reg(hi)));
3023          addInstr(env, PPCInstr_Cmp(False/*sign*/, True/*32bit cmp*/,
3024                                     7/*cr*/, tmp,PPCRH_Imm(False,0)));
3025          return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3026       } else {  // mode64
3027          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
3028          addInstr(env, PPCInstr_Cmp(False/*sign*/, False/*64bit cmp*/,
3029                                     7/*cr*/, r_src,PPCRH_Imm(False,0)));
3030          return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3031       }
3032    }
3033 
3034    /* --- patterns rooted at: Cmp*64* --- */
3035 
3036    /* Cmp*64*(x,y) */
3037    if (e->tag == Iex_Binop
3038        && (e->Iex.Binop.op == Iop_CmpEQ64
3039            || e->Iex.Binop.op == Iop_CmpNE64
3040            || e->Iex.Binop.op == Iop_CmpLT64S
3041            || e->Iex.Binop.op == Iop_CmpLT64U
3042            || e->Iex.Binop.op == Iop_CmpLE64S
3043            || e->Iex.Binop.op == Iop_CmpLE64U)) {
3044       Bool   syned = (e->Iex.Binop.op == Iop_CmpLT64S ||
3045                       e->Iex.Binop.op == Iop_CmpLE64S);
3046       HReg    r1 = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3047       PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2, IEndianess);
3048       vassert(env->mode64);
3049       addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
3050                                  7/*cr*/, r1, ri2));
3051 
3052       switch (e->Iex.Binop.op) {
3053       case Iop_CmpEQ64:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
3054       case Iop_CmpNE64:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3055       case Iop_CmpLT64U: return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
3056       case Iop_CmpLE64U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
3057       default: vpanic("iselCondCode(ppc): CmpXX64");
3058       }
3059    }
3060 
3061    /* --- patterns rooted at: CmpNE8 --- */
3062 
3063    /* CmpNE8(x,0) */
3064    /* Note this is a direct copy of CmpNEZ8 above. */
3065    /* could do better -- andi. */
3066    if (e->tag == Iex_Binop
3067        && e->Iex.Binop.op == Iop_CmpNE8
3068        && isZeroU8(e->Iex.Binop.arg2)) {
3069       HReg arg = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3070       HReg tmp = newVRegI(env);
3071       addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
3072                                  PPCRH_Imm(False,0xFF)));
3073       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3074                                  7/*cr*/, tmp, PPCRH_Imm(False,0)));
3075       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
3076    }
3077 
3078    /* var */
3079    if (e->tag == Iex_RdTmp) {
3080       HReg r_src      = lookupIRTemp(env, e->Iex.RdTmp.tmp);
3081       HReg src_masked = newVRegI(env);
3082       addInstr(env,
3083                PPCInstr_Alu(Palu_AND, src_masked,
3084                             r_src, PPCRH_Imm(False,1)));
3085       addInstr(env,
3086                PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
3087                             7/*cr*/, src_masked, PPCRH_Imm(False,1)));
3088       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
3089    }
3090 
3091    vex_printf("iselCondCode(ppc): No such tag(%u)\n", e->tag);
3092    ppIRExpr(e);
3093    vpanic("iselCondCode(ppc)");
3094 }
3095 
3096 
3097 /*---------------------------------------------------------*/
3098 /*--- ISEL: Integer expressions (128 bit)               ---*/
3099 /*---------------------------------------------------------*/
3100 
3101 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
3102    which is returned as the first two parameters.  As with
3103    iselWordExpr_R, these may be either real or virtual regs; in any
3104    case they must not be changed by subsequent code emitted by the
3105    caller.  */
3106 
iselInt128Expr(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3107 static void iselInt128Expr ( HReg* rHi, HReg* rLo, ISelEnv* env,
3108                              const IRExpr* e, IREndness IEndianess )
3109 {
3110    vassert(env->mode64);
3111    iselInt128Expr_wrk(rHi, rLo, env, e, IEndianess);
3112 #  if 0
3113    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3114 #  endif
3115    vassert(hregClass(*rHi) == HRcGPR(env->mode64));
3116    vassert(hregIsVirtual(*rHi));
3117    vassert(hregClass(*rLo) == HRcGPR(env->mode64));
3118    vassert(hregIsVirtual(*rLo));
3119 }
3120 
3121 /* DO NOT CALL THIS DIRECTLY ! */
iselInt128Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3122 static void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env,
3123                                  const IRExpr* e, IREndness IEndianess )
3124 {
3125    Bool mode64 = env->mode64;
3126 
3127    vassert(e);
3128    vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
3129 
3130    /* read 128-bit IRTemp */
3131    if (e->tag == Iex_RdTmp) {
3132       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
3133       return;
3134    }
3135 
3136    /* 128-bit GET */
3137    if (e->tag == Iex_Get) {
3138       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3139                                        GuestStatePtr(mode64) );
3140       PPCAMode* am_addr4 = advance4(env, am_addr);
3141       HReg tLo = newVRegI(env);
3142       HReg tHi = newVRegI(env);
3143 
3144       addInstr(env, PPCInstr_Load( 8, tHi, am_addr,  mode64));
3145       addInstr(env, PPCInstr_Load( 8, tLo, am_addr4, mode64));
3146       *rHi = tHi;
3147       *rLo = tLo;
3148       return;
3149    }
3150 
3151    /* --------- BINARY ops --------- */
3152    if (e->tag == Iex_Binop) {
3153       switch (e->Iex.Binop.op) {
3154       /* 64 x 64 -> 128 multiply */
3155       case Iop_MullU64:
3156       case Iop_MullS64: {
3157          HReg     tLo     = newVRegI(env);
3158          HReg     tHi     = newVRegI(env);
3159          Bool     syned   = toBool(e->Iex.Binop.op == Iop_MullS64);
3160          HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3161          HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
3162          addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
3163                                      False/*lo64*/, False/*64bit mul*/,
3164                                      tLo, r_srcL, r_srcR));
3165          addInstr(env, PPCInstr_MulL(syned,
3166                                      True/*hi64*/, False/*64bit mul*/,
3167                                      tHi, r_srcL, r_srcR));
3168          *rHi = tHi;
3169          *rLo = tLo;
3170          return;
3171       }
3172 
3173       /* 64HLto128(e1,e2) */
3174       case Iop_64HLto128:
3175          *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3176          *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
3177          return;
3178       default:
3179          break;
3180       }
3181    } /* if (e->tag == Iex_Binop) */
3182 
3183 
3184    /* --------- UNARY ops --------- */
3185    if (e->tag == Iex_Unop) {
3186       switch (e->Iex.Unop.op) {
3187       default:
3188          break;
3189       }
3190    } /* if (e->tag == Iex_Unop) */
3191 
3192    vex_printf("iselInt128Expr(ppc64): No such tag(%u)\n", e->tag);
3193    ppIRExpr(e);
3194    vpanic("iselInt128Expr(ppc64)");
3195 }
3196 
3197 
3198 /*---------------------------------------------------------*/
3199 /*--- ISEL: Integer expressions (64 bit)                ---*/
3200 /*---------------------------------------------------------*/
3201 
3202 /* 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)3203 static void iselInt128Expr_to_32x4 ( HReg* rHi, HReg* rMedHi, HReg* rMedLo,
3204                                      HReg* rLo, ISelEnv* env, const IRExpr* e,
3205                                      IREndness IEndianess )
3206 {
3207    vassert(!env->mode64);
3208    iselInt128Expr_to_32x4_wrk(rHi, rMedHi, rMedLo, rLo, env, e, IEndianess);
3209 #  if 0
3210    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3211 #  endif
3212    vassert(hregClass(*rHi) == HRcInt32);
3213    vassert(hregIsVirtual(*rHi));
3214    vassert(hregClass(*rMedHi) == HRcInt32);
3215    vassert(hregIsVirtual(*rMedHi));
3216    vassert(hregClass(*rMedLo) == HRcInt32);
3217    vassert(hregIsVirtual(*rMedLo));
3218    vassert(hregClass(*rLo) == HRcInt32);
3219    vassert(hregIsVirtual(*rLo));
3220 }
3221 
iselInt128Expr_to_32x4_wrk(HReg * rHi,HReg * rMedHi,HReg * rMedLo,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3222 static void iselInt128Expr_to_32x4_wrk ( HReg* rHi, HReg* rMedHi,
3223                                          HReg* rMedLo, HReg* rLo,
3224                                          ISelEnv* env, const IRExpr* e,
3225                                          IREndness IEndianess )
3226 {
3227    vassert(e);
3228    vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
3229 
3230    /* read 128-bit IRTemp */
3231    if (e->tag == Iex_RdTmp) {
3232       lookupIRTempQuad( rHi, rMedHi, rMedLo, rLo, env, e->Iex.RdTmp.tmp);
3233       return;
3234    }
3235 
3236    if (e->tag == Iex_Binop) {
3237 
3238       IROp op_binop = e->Iex.Binop.op;
3239       switch (op_binop) {
3240       case Iop_64HLto128:
3241          iselInt64Expr(rHi, rMedHi, env, e->Iex.Binop.arg1, IEndianess);
3242          iselInt64Expr(rMedLo, rLo, env, e->Iex.Binop.arg2, IEndianess);
3243          return;
3244       default:
3245          vex_printf("iselInt128Expr_to_32x4_wrk: Binop case 0x%x not found\n",
3246                     op_binop);
3247          break;
3248       }
3249    }
3250 
3251    vex_printf("iselInt128Expr_to_32x4_wrk: e->tag 0x%x not found\n", e->tag);
3252    return;
3253 }
3254 
3255 /* 32-bit mode ONLY: compute a 64-bit value into a register pair,
3256    which is returned as the first two parameters.  As with
3257    iselIntExpr_R, these may be either real or virtual regs; in any
3258    case they must not be changed by subsequent code emitted by the
3259    caller.  */
3260 
iselInt64Expr(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3261 static void iselInt64Expr ( HReg* rHi, HReg* rLo,
3262                             ISelEnv* env, const IRExpr* e,
3263                             IREndness IEndianess )
3264 {
3265    vassert(!env->mode64);
3266    iselInt64Expr_wrk(rHi, rLo, env, e, IEndianess);
3267 #  if 0
3268    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3269 #  endif
3270    vassert(hregClass(*rHi) == HRcInt32);
3271    vassert(hregIsVirtual(*rHi));
3272    vassert(hregClass(*rLo) == HRcInt32);
3273    vassert(hregIsVirtual(*rLo));
3274 }
3275 
3276 /* DO NOT CALL THIS DIRECTLY ! */
iselInt64Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)3277 static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
3278                                 ISelEnv* env, const IRExpr* e,
3279                                 IREndness IEndianess )
3280 {
3281    vassert(e);
3282    vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
3283 
3284    /* 64-bit load */
3285    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
3286       HReg tLo    = newVRegI(env);
3287       HReg tHi    = newVRegI(env);
3288       HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr, IEndianess);
3289       vassert(!env->mode64);
3290       addInstr(env, PPCInstr_Load( 4/*byte-load*/,
3291                                    tHi, PPCAMode_IR( 0, r_addr ),
3292                                    False/*32-bit insn please*/) );
3293       addInstr(env, PPCInstr_Load( 4/*byte-load*/,
3294                                    tLo, PPCAMode_IR( 4, r_addr ),
3295                                    False/*32-bit insn please*/) );
3296       *rHi = tHi;
3297       *rLo = tLo;
3298       return;
3299    }
3300 
3301    /* 64-bit literal */
3302    if (e->tag == Iex_Const) {
3303       ULong w64 = e->Iex.Const.con->Ico.U64;
3304       UInt  wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
3305       UInt  wLo = ((UInt)w64) & 0xFFFFFFFF;
3306       HReg  tLo = newVRegI(env);
3307       HReg  tHi = newVRegI(env);
3308       vassert(e->Iex.Const.con->tag == Ico_U64);
3309       addInstr(env, PPCInstr_LI(tHi, (Long)(Int)wHi, False/*mode32*/));
3310       addInstr(env, PPCInstr_LI(tLo, (Long)(Int)wLo, False/*mode32*/));
3311       *rHi = tHi;
3312       *rLo = tLo;
3313       return;
3314    }
3315 
3316    /* read 64-bit IRTemp */
3317    if (e->tag == Iex_RdTmp) {
3318       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
3319       return;
3320    }
3321 
3322    /* 64-bit GET */
3323    if (e->tag == Iex_Get) {
3324       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3325                                        GuestStatePtr(False/*mode32*/) );
3326       PPCAMode* am_addr4 = advance4(env, am_addr);
3327       HReg tLo = newVRegI(env);
3328       HReg tHi = newVRegI(env);
3329       addInstr(env, PPCInstr_Load( 4, tHi, am_addr,  False/*mode32*/ ));
3330       addInstr(env, PPCInstr_Load( 4, tLo, am_addr4, False/*mode32*/ ));
3331       *rHi = tHi;
3332       *rLo = tLo;
3333       return;
3334    }
3335 
3336    /* --------- CCALL --------- */
3337    if(e->tag == Iex_CCall) {
3338       IRType ty = typeOfIRExpr(env->type_env,e);
3339       Bool mode64 = env->mode64;
3340 
3341       vassert(ty == e->Iex.CCall.retty); /* well-formedness of IR */
3342 
3343       /* be very restrictive for now.  Only 32-bit ints allowed for
3344          args, and 32 bits or host machine word for return type. */
3345       vassert(!(ty == Ity_I32 || (mode64 && ty == Ity_I64)));
3346 
3347       /* Marshal args, do the call, clear stack. */
3348       UInt   addToSp = 0;
3349       RetLoc rloc    = mk_RetLoc_INVALID();
3350       doHelperCall( &addToSp, &rloc, env, NULL/*guard*/,
3351                     e->Iex.CCall.cee, e->Iex.CCall.retty, e->Iex.CCall.args,
3352                     IEndianess );
3353       vassert(is_sane_RetLoc(rloc));
3354 
3355       vassert(rloc.pri == RLPri_2Int);
3356       vassert(addToSp == 0);
3357 
3358       /* GPR3 now holds the destination address from Pin_Goto */
3359       HReg r_dst = newVRegI(env);
3360       addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
3361       *rHi = r_dst;
3362       *rLo = r_dst;
3363       return;
3364    }
3365 
3366    /* 64-bit ITE */
3367    if (e->tag == Iex_ITE) { // VFD
3368       HReg e0Lo, e0Hi, eXLo, eXHi;
3369       iselInt64Expr(&eXHi, &eXLo, env, e->Iex.ITE.iftrue, IEndianess);
3370       iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.ITE.iffalse, IEndianess);
3371       HReg tLo = newVRegI(env);
3372       HReg tHi = newVRegI(env);
3373       addInstr(env, mk_iMOVds_RR(tHi,e0Hi));
3374       addInstr(env, mk_iMOVds_RR(tLo,e0Lo));
3375       PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond, IEndianess);
3376       addInstr(env, PPCInstr_CMov(cc,tHi,PPCRI_Reg(eXHi)));
3377       addInstr(env, PPCInstr_CMov(cc,tLo,PPCRI_Reg(eXLo)));
3378       *rHi = tHi;
3379       *rLo = tLo;
3380       return;
3381    }
3382 
3383    /* --------- BINARY ops --------- */
3384    if (e->tag == Iex_Binop) {
3385       IROp op_binop = e->Iex.Binop.op;
3386       switch (op_binop) {
3387          /* 32 x 32 -> 64 multiply */
3388          case Iop_MullU32:
3389          case Iop_MullS32: {
3390             HReg     tLo     = newVRegI(env);
3391             HReg     tHi     = newVRegI(env);
3392             Bool     syned   = toBool(op_binop == Iop_MullS32);
3393             HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1,
3394                                               IEndianess);
3395             HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2,
3396                                               IEndianess);
3397             addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
3398                                         False/*lo32*/, True/*32bit mul*/,
3399                                         tLo, r_srcL, r_srcR));
3400             addInstr(env, PPCInstr_MulL(syned,
3401                                         True/*hi32*/, True/*32bit mul*/,
3402                                         tHi, r_srcL, r_srcR));
3403             *rHi = tHi;
3404             *rLo = tLo;
3405             return;
3406          }
3407 
3408          /* Or64/And64/Xor64 */
3409          case Iop_Or64:
3410          case Iop_And64:
3411          case Iop_Xor64: {
3412             HReg xLo, xHi, yLo, yHi;
3413             HReg tLo = newVRegI(env);
3414             HReg tHi = newVRegI(env);
3415             PPCAluOp op = (op_binop == Iop_Or64) ? Palu_OR :
3416                           (op_binop == Iop_And64) ? Palu_AND : Palu_XOR;
3417             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1, IEndianess);
3418             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2, IEndianess);
3419             addInstr(env, PPCInstr_Alu(op, tHi, xHi, PPCRH_Reg(yHi)));
3420             addInstr(env, PPCInstr_Alu(op, tLo, xLo, PPCRH_Reg(yLo)));
3421             *rHi = tHi;
3422             *rLo = tLo;
3423             return;
3424          }
3425 
3426          /* Add64 */
3427          case Iop_Add64: {
3428             HReg xLo, xHi, yLo, yHi;
3429             HReg tLo = newVRegI(env);
3430             HReg tHi = newVRegI(env);
3431             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1, IEndianess);
3432             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2, IEndianess);
3433             addInstr(env, PPCInstr_AddSubC( True/*add*/, True /*set carry*/,
3434                                             tLo, xLo, yLo));
3435             addInstr(env, PPCInstr_AddSubC( True/*add*/, False/*read carry*/,
3436                                             tHi, xHi, yHi));
3437             *rHi = tHi;
3438             *rLo = tLo;
3439             return;
3440          }
3441 
3442          /* 32HLto64(e1,e2) */
3443          case Iop_32HLto64:
3444             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
3445             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
3446             return;
3447 
3448          /* F64toI64[S|U] */
3449          case Iop_F64toI64S: case Iop_F64toI64U: {
3450             HReg      tLo     = newVRegI(env);
3451             HReg      tHi     = newVRegI(env);
3452             HReg      r1      = StackFramePtr(env->mode64);
3453             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3454             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3455             HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2,
3456                                             IEndianess);
3457             HReg      ftmp    = newVRegF(env);
3458 
3459             vassert(!env->mode64);
3460             /* Set host rounding mode */
3461             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
3462 
3463             sub_from_sp( env, 16 );
3464             addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
3465                                           (op_binop == Iop_F64toI64S) ? True : False,
3466                                           True, ftmp, fsrc));
3467             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
3468             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3469             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3470             add_to_sp( env, 16 );
3471 
3472             ///* Restore default FPU rounding. */
3473             //set_FPU_rounding_default( env );
3474             *rHi = tHi;
3475             *rLo = tLo;
3476             return;
3477          }
3478          case Iop_D64toI64S: {
3479             HReg      tLo     = newVRegI(env);
3480             HReg      tHi     = newVRegI(env);
3481             HReg      r1      = StackFramePtr(env->mode64);
3482             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3483             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3484             HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
3485             HReg tmp    = newVRegF(env);
3486 
3487             vassert(!env->mode64);
3488             set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
3489             addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTFIX, tmp, fr_src));
3490 
3491             sub_from_sp( env, 16 );
3492             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
3493             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3494             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3495             add_to_sp( env, 16 );
3496             *rHi = tHi;
3497             *rLo = tLo;
3498             return;
3499          }
3500          case Iop_D128toI64S: {
3501             PPCFpOp fpop = Pfp_DCTFIXQ;
3502             HReg r_srcHi = newVRegF(env);
3503             HReg r_srcLo = newVRegF(env);
3504             HReg tLo     = newVRegI(env);
3505             HReg tHi     = newVRegI(env);
3506             HReg ftmp    = newVRegF(env);
3507             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3508             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
3509 
3510             set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
3511             iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
3512                            IEndianess);
3513             addInstr(env, PPCInstr_DfpD128toD64(fpop, ftmp, r_srcHi, r_srcLo));
3514 
3515             // put the D64 result into an integer register pair
3516             sub_from_sp( env, 16 );
3517             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
3518             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3519             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3520             add_to_sp( env, 16 );
3521             *rHi = tHi;
3522             *rLo = tLo;
3523             return;
3524          }
3525          default:
3526             break;
3527       }
3528    } /* if (e->tag == Iex_Binop) */
3529 
3530 
3531    /* --------- UNARY ops --------- */
3532    if (e->tag == Iex_Unop) {
3533       switch (e->Iex.Unop.op) {
3534 
3535       /* CmpwNEZ64(e) */
3536       case Iop_CmpwNEZ64: {
3537          HReg argHi, argLo;
3538          HReg tmp1  = newVRegI(env);
3539          HReg tmp2  = newVRegI(env);
3540          iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg, IEndianess);
3541          /* tmp1 = argHi | argLo */
3542          addInstr(env, PPCInstr_Alu(Palu_OR, tmp1, argHi, PPCRH_Reg(argLo)));
3543          /* tmp2 = (tmp1 | -tmp1) >>s 31 */
3544          addInstr(env, PPCInstr_Unary(Pun_NEG,tmp2,tmp1));
3545          addInstr(env, PPCInstr_Alu(Palu_OR, tmp2, tmp2, PPCRH_Reg(tmp1)));
3546          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3547                                      tmp2, tmp2, PPCRH_Imm(False, 31)));
3548          *rHi = tmp2;
3549          *rLo = tmp2; /* yes, really tmp2 */
3550          return;
3551       }
3552 
3553       /* Left64 */
3554       case Iop_Left64: {
3555          HReg argHi, argLo;
3556          HReg zero32 = newVRegI(env);
3557          HReg resHi  = newVRegI(env);
3558          HReg resLo  = newVRegI(env);
3559          iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg, IEndianess);
3560          vassert(env->mode64 == False);
3561          addInstr(env, PPCInstr_LI(zero32, 0, env->mode64));
3562          /* resHi:resLo = - argHi:argLo */
3563          addInstr(env, PPCInstr_AddSubC( False/*sub*/, True/*set carry*/,
3564                                          resLo, zero32, argLo ));
3565          addInstr(env, PPCInstr_AddSubC( False/*sub*/, False/*read carry*/,
3566                                          resHi, zero32, argHi ));
3567          /* resHi:resLo |= srcHi:srcLo */
3568          addInstr(env, PPCInstr_Alu(Palu_OR, resLo, resLo, PPCRH_Reg(argLo)));
3569          addInstr(env, PPCInstr_Alu(Palu_OR, resHi, resHi, PPCRH_Reg(argHi)));
3570          *rHi = resHi;
3571          *rLo = resLo;
3572          return;
3573       }
3574 
3575       /* 32Sto64(e) */
3576       case Iop_32Sto64: {
3577          HReg tHi = newVRegI(env);
3578          HReg src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
3579          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3580                                      tHi, src, PPCRH_Imm(False,31)));
3581          *rHi = tHi;
3582          *rLo = src;
3583          return;
3584       }
3585       case Iop_ExtractExpD64: {
3586          HReg tmp    = newVRegF(env);
3587          HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
3588          HReg      tLo     = newVRegI(env);
3589          HReg      tHi     = newVRegI(env);
3590          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3591          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
3592 
3593          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DXEX, tmp, fr_src));
3594 
3595          // put the D64 result into a integer register pair
3596          sub_from_sp( env, 16 );
3597          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
3598          addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3599          addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3600          add_to_sp( env, 16 );
3601          *rHi = tHi;
3602          *rLo = tLo;
3603          return;
3604       }
3605       case Iop_ExtractExpD128: {
3606          HReg      r_srcHi;
3607          HReg      r_srcLo;
3608          HReg      tmp     = newVRegF(env);
3609          HReg      tLo     = newVRegI(env);
3610          HReg      tHi     = newVRegI(env);
3611          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3612          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
3613 
3614          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Unop.arg, IEndianess);
3615          addInstr(env, PPCInstr_ExtractExpD128(Pfp_DXEXQ, tmp,
3616                                                   r_srcHi, r_srcLo));
3617 
3618          // put the D64 result into a integer register pair
3619          sub_from_sp( env, 16 );
3620          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
3621          addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3622          addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3623          add_to_sp( env, 16 );
3624          *rHi = tHi;
3625          *rLo = tLo;
3626          return;
3627       }
3628 
3629       /* 32Uto64(e) */
3630       case Iop_32Uto64: {
3631          HReg tHi = newVRegI(env);
3632          HReg tLo = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
3633          addInstr(env, PPCInstr_LI(tHi, 0, False/*mode32*/));
3634          *rHi = tHi;
3635          *rLo = tLo;
3636          return;
3637       }
3638 
3639       case Iop_128to64: {
3640          /* Narrow, return the low 64-bit half as a 32-bit
3641           * register pair */
3642          HReg r_Hi    = INVALID_HREG;
3643          HReg r_MedHi = INVALID_HREG;
3644          HReg r_MedLo = INVALID_HREG;
3645          HReg r_Lo    = INVALID_HREG;
3646 
3647          iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
3648                                 env, e->Iex.Unop.arg, IEndianess);
3649          *rHi = r_MedLo;
3650          *rLo = r_Lo;
3651          return;
3652       }
3653 
3654       case Iop_128HIto64: {
3655          /* Narrow, return the high 64-bit half as a 32-bit
3656           *  register pair */
3657          HReg r_Hi    = INVALID_HREG;
3658          HReg r_MedHi = INVALID_HREG;
3659          HReg r_MedLo = INVALID_HREG;
3660          HReg r_Lo    = INVALID_HREG;
3661 
3662          iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
3663                                 env, e->Iex.Unop.arg, IEndianess);
3664          *rHi = r_Hi;
3665          *rLo = r_MedHi;
3666          return;
3667       }
3668 
3669       /* V128{HI}to64 */
3670       case Iop_V128HIto64:
3671       case Iop_V128to64: {
3672          HReg r_aligned16;
3673          Int  off = e->Iex.Unop.op==Iop_V128HIto64 ? 0 : 8;
3674          HReg tLo = newVRegI(env);
3675          HReg tHi = newVRegI(env);
3676          HReg vec = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
3677          PPCAMode *am_off0, *am_offLO, *am_offHI;
3678          sub_from_sp( env, 32 );     // Move SP down 32 bytes
3679 
3680          // get a quadword aligned address within our stack space
3681          r_aligned16 = get_sp_aligned16( env );
3682          am_off0  = PPCAMode_IR( 0,     r_aligned16 );
3683          am_offHI = PPCAMode_IR( off,   r_aligned16 );
3684          am_offLO = PPCAMode_IR( off+4, r_aligned16 );
3685 
3686          // store as Vec128
3687          addInstr(env,
3688                   PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
3689 
3690          // load hi,lo words (of hi/lo half of vec) as Ity_I32's
3691          addInstr(env,
3692                   PPCInstr_Load( 4, tHi, am_offHI, False/*mode32*/ ));
3693          addInstr(env,
3694                   PPCInstr_Load( 4, tLo, am_offLO, False/*mode32*/ ));
3695 
3696          add_to_sp( env, 32 );       // Reset SP
3697          *rHi = tHi;
3698          *rLo = tLo;
3699          return;
3700       }
3701 
3702       /* could do better than this, but for now ... */
3703       case Iop_1Sto64: {
3704          HReg tLo = newVRegI(env);
3705          HReg tHi = newVRegI(env);
3706          PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
3707          addInstr(env, PPCInstr_Set(cond,tLo));
3708          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
3709                                      tLo, tLo, PPCRH_Imm(False,31)));
3710          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3711                                      tLo, tLo, PPCRH_Imm(False,31)));
3712          addInstr(env, mk_iMOVds_RR(tHi, tLo));
3713          *rHi = tHi;
3714          *rLo = tLo;
3715          return;
3716       }
3717 
3718       case Iop_Not64: {
3719          HReg xLo, xHi;
3720          HReg tmpLo = newVRegI(env);
3721          HReg tmpHi = newVRegI(env);
3722          iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg, IEndianess);
3723          addInstr(env, PPCInstr_Unary(Pun_NOT,tmpLo,xLo));
3724          addInstr(env, PPCInstr_Unary(Pun_NOT,tmpHi,xHi));
3725          *rHi = tmpHi;
3726          *rLo = tmpLo;
3727          return;
3728       }
3729 
3730       /* ReinterpF64asI64(e) */
3731       /* Given an IEEE754 double, produce an I64 with the same bit
3732          pattern. */
3733       case Iop_ReinterpF64asI64: {
3734          PPCAMode *am_addr0, *am_addr1;
3735          HReg fr_src  = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
3736          HReg r_dstLo = newVRegI(env);
3737          HReg r_dstHi = newVRegI(env);
3738 
3739          sub_from_sp( env, 16 );     // Move SP down 16 bytes
3740          am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
3741          am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
3742 
3743          // store as F64
3744          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
3745                                         fr_src, am_addr0 ));
3746 
3747          // load hi,lo as Ity_I32's
3748          addInstr(env, PPCInstr_Load( 4, r_dstHi,
3749                                       am_addr0, False/*mode32*/ ));
3750          addInstr(env, PPCInstr_Load( 4, r_dstLo,
3751                                       am_addr1, False/*mode32*/ ));
3752          *rHi = r_dstHi;
3753          *rLo = r_dstLo;
3754 
3755          add_to_sp( env, 16 );       // Reset SP
3756          return;
3757       }
3758 
3759       case Iop_ReinterpD64asI64: {
3760          HReg fr_src  = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
3761          PPCAMode *am_addr0, *am_addr1;
3762          HReg r_dstLo = newVRegI(env);
3763          HReg r_dstHi = newVRegI(env);
3764 
3765 
3766          sub_from_sp( env, 16 );     // Move SP down 16 bytes
3767          am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
3768          am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
3769 
3770          // store as D64
3771          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
3772                                         fr_src, am_addr0 ));
3773 
3774          // load hi,lo as Ity_I32's
3775          addInstr(env, PPCInstr_Load( 4, r_dstHi,
3776                                       am_addr0, False/*mode32*/ ));
3777          addInstr(env, PPCInstr_Load( 4, r_dstLo,
3778                                       am_addr1, False/*mode32*/ ));
3779          *rHi = r_dstHi;
3780          *rLo = r_dstLo;
3781 
3782          add_to_sp( env, 16 );       // Reset SP
3783 
3784          return;
3785       }
3786 
3787       case Iop_BCDtoDPB: {
3788          PPCCondCode cc;
3789          UInt        argiregs;
3790          HReg        argregs[2];
3791          Int         argreg;
3792          HReg        tLo = newVRegI(env);
3793          HReg        tHi = newVRegI(env);
3794          HReg        tmpHi;
3795          HReg        tmpLo;
3796          Bool        mode64 = env->mode64;
3797 
3798          argregs[0] = hregPPC_GPR3(mode64);
3799          argregs[1] = hregPPC_GPR4(mode64);
3800 
3801          argiregs = 0;
3802          argreg = 0;
3803 
3804          iselInt64Expr( &tmpHi, &tmpLo, env, e->Iex.Unop.arg, IEndianess );
3805 
3806          argiregs |= ( 1 << (argreg+3 ) );
3807          addInstr( env, mk_iMOVds_RR( argregs[argreg++], tmpHi ) );
3808 
3809          argiregs |= ( 1 << (argreg+3 ) );
3810          addInstr( env, mk_iMOVds_RR( argregs[argreg], tmpLo ) );
3811 
3812          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
3813 
3814          if (IEndianess == Iend_LE) {
3815              addInstr( env, PPCInstr_Call( cc, (Addr)h_calc_BCDtoDPB,
3816                                            argiregs,
3817                                            mk_RetLoc_simple(RLPri_2Int) ) );
3818          } else {
3819              Addr64 target;
3820              target = mode64 ? (Addr)h_calc_BCDtoDPB :
3821                toUInt( (Addr)h_calc_BCDtoDPB );
3822              addInstr( env, PPCInstr_Call( cc, target,
3823                                            argiregs,
3824                                            mk_RetLoc_simple(RLPri_2Int) ) );
3825          }
3826 
3827          addInstr( env, mk_iMOVds_RR( tHi, argregs[argreg-1] ) );
3828          addInstr( env, mk_iMOVds_RR( tLo, argregs[argreg] ) );
3829 
3830          *rHi = tHi;
3831          *rLo = tLo;
3832          return;
3833       }
3834 
3835       case Iop_DPBtoBCD: {
3836          PPCCondCode cc;
3837          UInt        argiregs;
3838          HReg        argregs[2];
3839          Int         argreg;
3840          HReg        tLo = newVRegI(env);
3841          HReg        tHi = newVRegI(env);
3842          HReg        tmpHi;
3843          HReg        tmpLo;
3844          Bool        mode64 = env->mode64;
3845 
3846          argregs[0] = hregPPC_GPR3(mode64);
3847          argregs[1] = hregPPC_GPR4(mode64);
3848 
3849          argiregs = 0;
3850          argreg = 0;
3851 
3852          iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg, IEndianess);
3853 
3854          argiregs |= (1 << (argreg+3));
3855          addInstr(env, mk_iMOVds_RR( argregs[argreg++], tmpHi ));
3856 
3857          argiregs |= (1 << (argreg+3));
3858          addInstr(env, mk_iMOVds_RR( argregs[argreg], tmpLo));
3859 
3860          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
3861 
3862          if (IEndianess == Iend_LE) {
3863              addInstr(env, PPCInstr_Call( cc, (Addr)h_calc_DPBtoBCD,
3864                                           argiregs,
3865                                           mk_RetLoc_simple(RLPri_2Int) ) );
3866          } else {
3867              Addr64 target;
3868              target = mode64 ? (Addr)h_calc_DPBtoBCD :
3869                toUInt( (Addr)h_calc_DPBtoBCD );
3870              addInstr(env, PPCInstr_Call( cc, target, argiregs,
3871                                           mk_RetLoc_simple(RLPri_2Int) ) );
3872          }
3873 
3874          addInstr(env, mk_iMOVds_RR(tHi, argregs[argreg-1]));
3875          addInstr(env, mk_iMOVds_RR(tLo, argregs[argreg]));
3876 
3877          *rHi = tHi;
3878          *rLo = tLo;
3879          return;
3880       }
3881 
3882       default:
3883          break;
3884       }
3885    } /* if (e->tag == Iex_Unop) */
3886 
3887    vex_printf("iselInt64Expr(ppc): No such tag(%u)\n", e->tag);
3888    ppIRExpr(e);
3889    vpanic("iselInt64Expr(ppc)");
3890 }
3891 
3892 
3893 /*---------------------------------------------------------*/
3894 /*--- ISEL: Floating point expressions (32 bit)         ---*/
3895 /*---------------------------------------------------------*/
3896 
3897 /* Nothing interesting here; really just wrappers for
3898    64-bit stuff. */
3899 
iselFltExpr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)3900 static HReg iselFltExpr ( ISelEnv* env, const IRExpr* e, IREndness IEndianess )
3901 {
3902   HReg r = iselFltExpr_wrk( env, e, IEndianess );
3903 #  if 0
3904    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3905 #  endif
3906    vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
3907    vassert(hregIsVirtual(r));
3908    return r;
3909 }
3910 
3911 /* DO NOT CALL THIS DIRECTLY */
iselFltExpr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)3912 static HReg iselFltExpr_wrk ( ISelEnv* env, const IRExpr* e,
3913                               IREndness IEndianess )
3914 {
3915    Bool        mode64 = env->mode64;
3916 
3917    IRType ty = typeOfIRExpr(env->type_env,e);
3918    vassert(ty == Ity_F32);
3919 
3920    if (e->tag == Iex_RdTmp) {
3921       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3922    }
3923 
3924    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
3925       PPCAMode* am_addr;
3926       HReg r_dst = newVRegF(env);
3927       vassert(e->Iex.Load.ty == Ity_F32);
3928       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F32/*xfer*/,
3929                                    IEndianess);
3930       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
3931       return r_dst;
3932    }
3933 
3934    if (e->tag == Iex_Get) {
3935       HReg r_dst = newVRegF(env);
3936       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3937                                        GuestStatePtr(env->mode64) );
3938       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4, r_dst, am_addr ));
3939       return r_dst;
3940    }
3941 
3942    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
3943       /* This is quite subtle.  The only way to do the relevant
3944          truncation is to do a single-precision store and then a
3945          double precision load to get it back into a register.  The
3946          problem is, if the data is then written to memory a second
3947          time, as in
3948 
3949             STbe(...) = TruncF64asF32(...)
3950 
3951          then will the second truncation further alter the value?  The
3952          answer is no: flds (as generated here) followed by fsts
3953          (generated for the STbe) is the identity function on 32-bit
3954          floats, so we are safe.
3955 
3956          Another upshot of this is that if iselStmt can see the
3957          entirety of
3958 
3959             STbe(...) = TruncF64asF32(arg)
3960 
3961          then it can short circuit having to deal with TruncF64asF32
3962          individually; instead just compute arg into a 64-bit FP
3963          register and do 'fsts' (since that itself does the
3964          truncation).
3965 
3966          We generate pretty poor code here (should be ok both for
3967          32-bit and 64-bit mode); but it is expected that for the most
3968          part the latter optimisation will apply and hence this code
3969          will not often be used.
3970       */
3971       HReg      fsrc    = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
3972       HReg      fdst    = newVRegF(env);
3973       PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3974 
3975       sub_from_sp( env, 16 );
3976       // store as F32, hence truncating
3977       addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
3978                                      fsrc, zero_r1 ));
3979       // and reload.  Good huh?! (sigh)
3980       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4,
3981                                      fdst, zero_r1 ));
3982       add_to_sp( env, 16 );
3983       return fdst;
3984    }
3985 
3986    if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64UtoF32) {
3987       if (mode64) {
3988          HReg fdst = newVRegF(env);
3989          HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
3990          HReg r1   = StackFramePtr(env->mode64);
3991          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3992 
3993          /* Set host rounding mode */
3994          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
3995 
3996          sub_from_sp( env, 16 );
3997 
3998          addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
3999          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
4000          addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
4001                                        False, False,
4002                                        fdst, fdst));
4003 
4004          add_to_sp( env, 16 );
4005 
4006          ///* Restore default FPU rounding. */
4007          //set_FPU_rounding_default( env );
4008          return fdst;
4009       } else {
4010          /* 32-bit mode */
4011          HReg fdst = newVRegF(env);
4012          HReg isrcHi, isrcLo;
4013          HReg r1   = StackFramePtr(env->mode64);
4014          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
4015          PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
4016 
4017          iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2, IEndianess);
4018 
4019          /* Set host rounding mode */
4020          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4021 
4022          sub_from_sp( env, 16 );
4023 
4024          addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
4025          addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
4026          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
4027          addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
4028                                        False, False,
4029                                        fdst, fdst));
4030 
4031          add_to_sp( env, 16 );
4032 
4033          ///* Restore default FPU rounding. */
4034          //set_FPU_rounding_default( env );
4035          return fdst;
4036       }
4037 
4038    }
4039 
4040    vex_printf("iselFltExpr(ppc): No such tag(%u)\n", e->tag);
4041    ppIRExpr(e);
4042    vpanic("iselFltExpr_wrk(ppc)");
4043 }
4044 
4045 
4046 /*---------------------------------------------------------*/
4047 /*--- ISEL: Floating point expressions (64 bit)         ---*/
4048 /*---------------------------------------------------------*/
4049 
4050 /* Compute a 64-bit floating point value into a register, the identity
4051    of which is returned.  As with iselIntExpr_R, the reg may be either
4052    real or virtual; in any case it must not be changed by subsequent
4053    code emitted by the caller.  */
4054 
4055 /* IEEE 754 formats.  From http://www.freesoft.org/CIE/RFC/1832/32.htm:
4056 
4057     Type                  S (1 bit)   E (11 bits)   F (52 bits)
4058     ----                  ---------   -----------   -----------
4059     signalling NaN        u           2047 (max)    .0uuuuu---u
4060                                                     (with at least
4061                                                      one 1 bit)
4062     quiet NaN             u           2047 (max)    .1uuuuu---u
4063 
4064     negative infinity     1           2047 (max)    .000000---0
4065 
4066     positive infinity     0           2047 (max)    .000000---0
4067 
4068     negative zero         1           0             .000000---0
4069 
4070     positive zero         0           0             .000000---0
4071 */
4072 
iselDblExpr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4073 static HReg iselDblExpr ( ISelEnv* env, const IRExpr* e, IREndness IEndianess )
4074 {
4075    HReg r = iselDblExpr_wrk( env, e, IEndianess );
4076 #  if 0
4077    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4078 #  endif
4079    vassert(hregClass(r) == HRcFlt64);
4080    vassert(hregIsVirtual(r));
4081    return r;
4082 }
4083 
4084 /* DO NOT CALL THIS DIRECTLY */
iselDblExpr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4085 static HReg iselDblExpr_wrk ( ISelEnv* env, const IRExpr* e,
4086                               IREndness IEndianess )
4087 {
4088    Bool mode64 = env->mode64;
4089    IRType ty = typeOfIRExpr(env->type_env,e);
4090    vassert(e);
4091    vassert(ty == Ity_F64);
4092 
4093    if (e->tag == Iex_RdTmp) {
4094       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
4095    }
4096 
4097    /* --------- LITERAL --------- */
4098    if (e->tag == Iex_Const) {
4099       union { UInt u32x2[2]; ULong u64; Double f64; } u;
4100       vassert(sizeof(u) == 8);
4101       vassert(sizeof(u.u64) == 8);
4102       vassert(sizeof(u.f64) == 8);
4103       vassert(sizeof(u.u32x2) == 8);
4104 
4105       if (e->Iex.Const.con->tag == Ico_F64) {
4106          u.f64 = e->Iex.Const.con->Ico.F64;
4107       }
4108       else if (e->Iex.Const.con->tag == Ico_F64i) {
4109          u.u64 = e->Iex.Const.con->Ico.F64i;
4110       }
4111       else
4112          vpanic("iselDblExpr(ppc): const");
4113 
4114       if (!mode64) {
4115          HReg r_srcHi = newVRegI(env);
4116          HReg r_srcLo = newVRegI(env);
4117          addInstr(env, PPCInstr_LI(r_srcHi, u.u32x2[0], mode64));
4118          addInstr(env, PPCInstr_LI(r_srcLo, u.u32x2[1], mode64));
4119          return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
4120       } else { // mode64
4121          HReg r_src = newVRegI(env);
4122          addInstr(env, PPCInstr_LI(r_src, u.u64, mode64));
4123          return mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
4124       }
4125    }
4126 
4127    /* --------- LOAD --------- */
4128    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
4129       HReg r_dst = newVRegF(env);
4130       PPCAMode* am_addr;
4131       vassert(e->Iex.Load.ty == Ity_F64);
4132       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F64/*xfer*/,
4133                                    IEndianess);
4134       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
4135       return r_dst;
4136    }
4137 
4138    /* --------- GET --------- */
4139    if (e->tag == Iex_Get) {
4140       HReg r_dst = newVRegF(env);
4141       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
4142                                        GuestStatePtr(mode64) );
4143       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ));
4144       return r_dst;
4145    }
4146 
4147    /* --------- OPS --------- */
4148    if (e->tag == Iex_Qop) {
4149       PPCFpOp fpop = Pfp_INVALID;
4150       switch (e->Iex.Qop.details->op) {
4151          case Iop_MAddF64:    fpop = Pfp_MADDD; break;
4152          case Iop_MAddF64r32: fpop = Pfp_MADDS; break;
4153          case Iop_MSubF64:    fpop = Pfp_MSUBD; break;
4154          case Iop_MSubF64r32: fpop = Pfp_MSUBS; break;
4155          default: break;
4156       }
4157       if (fpop != Pfp_INVALID) {
4158          HReg r_dst  = newVRegF(env);
4159          HReg r_srcML  = iselDblExpr(env, e->Iex.Qop.details->arg2,
4160                                      IEndianess);
4161          HReg r_srcMR  = iselDblExpr(env, e->Iex.Qop.details->arg3,
4162                                      IEndianess);
4163          HReg r_srcAcc = iselDblExpr(env, e->Iex.Qop.details->arg4,
4164                                      IEndianess);
4165          set_FPU_rounding_mode( env, e->Iex.Qop.details->arg1, IEndianess );
4166          addInstr(env, PPCInstr_FpMulAcc(fpop, r_dst,
4167                                                r_srcML, r_srcMR, r_srcAcc));
4168          return r_dst;
4169       }
4170    }
4171 
4172    if (e->tag == Iex_Triop) {
4173       IRTriop *triop = e->Iex.Triop.details;
4174       PPCFpOp fpop = Pfp_INVALID;
4175       switch (triop->op) {
4176          case Iop_AddF64:    fpop = Pfp_ADDD; break;
4177          case Iop_SubF64:    fpop = Pfp_SUBD; break;
4178          case Iop_MulF64:    fpop = Pfp_MULD; break;
4179          case Iop_DivF64:    fpop = Pfp_DIVD; break;
4180          case Iop_AddF64r32: fpop = Pfp_ADDS; break;
4181          case Iop_SubF64r32: fpop = Pfp_SUBS; break;
4182          case Iop_MulF64r32: fpop = Pfp_MULS; break;
4183          case Iop_DivF64r32: fpop = Pfp_DIVS; break;
4184          default: break;
4185       }
4186       if (fpop != Pfp_INVALID) {
4187          HReg r_dst  = newVRegF(env);
4188          HReg r_srcL = iselDblExpr(env, triop->arg2, IEndianess);
4189          HReg r_srcR = iselDblExpr(env, triop->arg3, IEndianess);
4190          set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4191          addInstr(env, PPCInstr_FpBinary(fpop, r_dst, r_srcL, r_srcR));
4192          return r_dst;
4193       }
4194    }
4195 
4196    if (e->tag == Iex_Binop) {
4197       PPCFpOp fpop = Pfp_INVALID;
4198       switch (e->Iex.Binop.op) {
4199       case Iop_SqrtF64:   fpop = Pfp_SQRT;   break;
4200       default: break;
4201       }
4202       if (fpop == Pfp_SQRT) {
4203          HReg fr_dst = newVRegF(env);
4204          HReg fr_src = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
4205          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4206          addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
4207          return fr_dst;
4208       }
4209    }
4210 
4211    if (e->tag == Iex_Binop) {
4212 
4213       if (e->Iex.Binop.op == Iop_F128toF64) {
4214          HReg fr_dst = newVRegF(env);
4215          HReg fr_src = iselFp128Expr(env, e->Iex.Binop.arg2, IEndianess);
4216          HReg tmp = newVRegV(env);
4217          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4218          PPCAMode* eight_r1 = PPCAMode_IR( 8, StackFramePtr(env->mode64) );
4219          PPCFpOp fpop = Pfp_INVALID;
4220 
4221          if (FPU_rounding_mode_isOdd(e->Iex.Binop.arg1)) {
4222             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4223             fpop = Pfp_FPQTODRNDODD;
4224          } else {
4225             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4226             fpop = Pfp_FPQTOD;
4227          }
4228 
4229          addInstr(env, PPCInstr_Fp128Unary(fpop, tmp, fr_src));
4230 
4231          /* result is in a 128-bit vector register, move to 64-bit reg to
4232           * match the Iop specification.  The result will get moved back
4233           * to a 128-bit register and stored once the value is returned.
4234           */
4235          sub_from_sp( env, 16 );
4236          addInstr(env, PPCInstr_AvLdSt(False/*store*/, 16, tmp, zero_r1));
4237          if (IEndianess == Iend_LE)
4238             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, eight_r1));
4239          else
4240             /* High 64-bits stored at lower address */
4241             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, zero_r1));
4242 
4243          add_to_sp( env, 16 );
4244 
4245          return fr_dst;
4246       }
4247 
4248       if (e->Iex.Binop.op == Iop_RoundF64toF32) {
4249          HReg r_dst = newVRegF(env);
4250          HReg r_src = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
4251          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4252          addInstr(env, PPCInstr_FpRSP(r_dst, r_src));
4253          //set_FPU_rounding_default( env );
4254          return r_dst;
4255       }
4256 
4257       if (e->Iex.Binop.op == Iop_I64StoF64 || e->Iex.Binop.op == Iop_I64UtoF64) {
4258          if (mode64) {
4259             HReg fdst = newVRegF(env);
4260             HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
4261             HReg r1   = StackFramePtr(env->mode64);
4262             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
4263 
4264             /* Set host rounding mode */
4265             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4266 
4267             sub_from_sp( env, 16 );
4268 
4269             addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
4270             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
4271             addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
4272                                           e->Iex.Binop.op == Iop_I64StoF64,
4273                                           True/*fdst is 64 bit*/,
4274                                           fdst, fdst));
4275 
4276             add_to_sp( env, 16 );
4277 
4278             ///* Restore default FPU rounding. */
4279             //set_FPU_rounding_default( env );
4280             return fdst;
4281          } else {
4282             /* 32-bit mode */
4283             HReg fdst = newVRegF(env);
4284             HReg isrcHi, isrcLo;
4285             HReg r1   = StackFramePtr(env->mode64);
4286             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
4287             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
4288 
4289             iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2,
4290                           IEndianess);
4291 
4292             /* Set host rounding mode */
4293             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4294 
4295             sub_from_sp( env, 16 );
4296 
4297             addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
4298             addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
4299             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
4300             addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
4301                                           e->Iex.Binop.op == Iop_I64StoF64,
4302                                           True/*fdst is 64 bit*/,
4303                                           fdst, fdst));
4304 
4305             add_to_sp( env, 16 );
4306 
4307             ///* Restore default FPU rounding. */
4308             //set_FPU_rounding_default( env );
4309             return fdst;
4310          }
4311       }
4312 
4313    }
4314 
4315    if (e->tag == Iex_Unop) {
4316       PPCFpOp fpop = Pfp_INVALID;
4317       switch (e->Iex.Unop.op) {
4318          case Iop_NegF64:     fpop = Pfp_NEG; break;
4319          case Iop_AbsF64:     fpop = Pfp_ABS; break;
4320          case Iop_RSqrtEst5GoodF64:      fpop = Pfp_RSQRTE; break;
4321          case Iop_RoundF64toF64_NegINF:  fpop = Pfp_FRIM; break;
4322          case Iop_RoundF64toF64_PosINF:  fpop = Pfp_FRIP; break;
4323          case Iop_RoundF64toF64_NEAREST: fpop = Pfp_FRIN; break;
4324          case Iop_RoundF64toF64_ZERO:    fpop = Pfp_FRIZ; break;
4325          default: break;
4326       }
4327       if (fpop != Pfp_INVALID) {
4328          HReg fr_dst = newVRegF(env);
4329          HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
4330          addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
4331          return fr_dst;
4332       }
4333    }
4334 
4335    if (e->tag == Iex_Unop) {
4336       switch (e->Iex.Unop.op) {
4337       case Iop_F128HItoF64:
4338       case Iop_F128LOtoF64:
4339          {
4340             /* put upper/lower 64-bits of F128 into an F64. */
4341             HReg     r_aligned16;
4342             HReg     fdst = newVRegF(env);
4343             HReg     fsrc = iselFp128Expr(env, e->Iex.Unop.arg, IEndianess);
4344             PPCAMode *am_off0, *am_off8, *am_off_arg;
4345             sub_from_sp( env, 32 );     // Move SP down 32 bytes
4346 
4347             // get a quadword aligned address within our stack space
4348             r_aligned16 = get_sp_aligned16( env );
4349             am_off0 = PPCAMode_IR( 0, r_aligned16 );
4350             am_off8 = PPCAMode_IR( 8 ,r_aligned16 );
4351 
4352             /* store 128-bit floating point value to memory, load low word
4353              * or high to 64-bit destination floating point register
4354              */
4355             addInstr(env, PPCInstr_AvLdSt(False/*store*/, 16, fsrc, am_off0));
4356             if (IEndianess == Iend_LE) {
4357                if (e->Iex.Binop.op == Iop_F128HItoF64)
4358                   am_off_arg = am_off8;
4359                else
4360                   am_off_arg = am_off0;
4361             } else {
4362                if (e->Iex.Binop.op == Iop_F128HItoF64)
4363                   am_off_arg = am_off0;
4364                else
4365                   am_off_arg = am_off8;
4366             }
4367             addInstr(env,
4368                     PPCInstr_FpLdSt( True /*load*/,
4369                                       8, fdst,
4370                                       am_off_arg ));
4371             add_to_sp( env, 32 );       // Reset SP
4372             return fdst;
4373          }
4374          case Iop_ReinterpI64asF64: {
4375             /* Given an I64, produce an IEEE754 double with the same
4376                bit pattern. */
4377             if (!mode64) {
4378                HReg r_srcHi, r_srcLo;
4379                iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg,
4380                                IEndianess);
4381                return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
4382             } else {
4383                HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
4384                return mk_LoadR64toFPR( env, r_src );
4385             }
4386          }
4387 
4388          case Iop_F32toF64: {
4389             if (e->Iex.Unop.arg->tag == Iex_Unop &&
4390                      e->Iex.Unop.arg->Iex.Unop.op == Iop_ReinterpI32asF32 ) {
4391                e = e->Iex.Unop.arg;
4392 
4393                HReg src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
4394                HReg fr_dst = newVRegF(env);
4395                PPCAMode *am_addr;
4396 
4397                sub_from_sp( env, 16 );        // Move SP down 16 bytes
4398                am_addr = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4399 
4400                // store src as Ity_I32's
4401                addInstr(env, PPCInstr_Store( 4, am_addr, src, env->mode64 ));
4402 
4403                // load single precision float, but the end results loads into a
4404                // 64-bit FP register -- i.e., F64.
4405                addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, fr_dst, am_addr));
4406 
4407                add_to_sp( env, 16 );          // Reset SP
4408                return fr_dst;
4409             }
4410 
4411 
4412             /* this is a no-op */
4413             HReg res = iselFltExpr(env, e->Iex.Unop.arg, IEndianess);
4414             return res;
4415          }
4416          default:
4417             break;
4418       }
4419    }
4420 
4421    /* --------- MULTIPLEX --------- */
4422    if (e->tag == Iex_ITE) { // VFD
4423       if (ty == Ity_F64
4424           && typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) {
4425          HReg fr1    = iselDblExpr(env, e->Iex.ITE.iftrue, IEndianess);
4426          HReg fr0    = iselDblExpr(env, e->Iex.ITE.iffalse, IEndianess);
4427          HReg fr_dst = newVRegF(env);
4428          addInstr(env, PPCInstr_FpUnary( Pfp_MOV, fr_dst, fr0 ));
4429          PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond, IEndianess);
4430          addInstr(env, PPCInstr_FpCMov( cc, fr_dst, fr1 ));
4431          return fr_dst;
4432       }
4433    }
4434 
4435    vex_printf("iselDblExpr(ppc): No such tag(%u)\n", e->tag);
4436    ppIRExpr(e);
4437    vpanic("iselDblExpr_wrk(ppc)");
4438 }
4439 
iselDfp32Expr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4440 static HReg iselDfp32Expr(ISelEnv* env, const IRExpr* e, IREndness IEndianess)
4441 {
4442    HReg r = iselDfp32Expr_wrk( env, e, IEndianess );
4443    vassert(hregClass(r) == HRcFlt64);
4444    vassert( hregIsVirtual(r) );
4445    return r;
4446 }
4447 
4448 /* DO NOT CALL THIS DIRECTLY */
iselDfp32Expr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4449 static HReg iselDfp32Expr_wrk(ISelEnv* env, const IRExpr* e,
4450                               IREndness IEndianess)
4451 {
4452    Bool mode64 = env->mode64;
4453    IRType ty = typeOfIRExpr( env->type_env, e );
4454 
4455    vassert( e );
4456    vassert( ty == Ity_D32 );
4457 
4458    /* --------- GET --------- */
4459    if (e->tag == Iex_Get) {
4460       HReg r_dst = newVRegF( env );
4461       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
4462                                        GuestStatePtr(mode64) );
4463       addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
4464       return r_dst;
4465    }
4466 
4467    /* --------- LOAD --------- */
4468    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
4469       PPCAMode* am_addr;
4470       HReg r_dst = newVRegF(env);
4471       vassert(e->Iex.Load.ty == Ity_D32);
4472       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D32/*xfer*/,
4473                                    IEndianess);
4474       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
4475       return r_dst;
4476    }
4477 
4478    /* --------- OPS --------- */
4479    if (e->tag == Iex_Binop) {
4480       if (e->Iex.Binop.op == Iop_D64toD32) {
4481          HReg fr_dst = newVRegF(env);
4482          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
4483          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4484          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DRSP, fr_dst, fr_src));
4485          return fr_dst;
4486       }
4487    }
4488 
4489    ppIRExpr( e );
4490    vpanic( "iselDfp32Expr_wrk(ppc)" );
4491 }
4492 
iselFp128Expr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4493 static HReg iselFp128Expr( ISelEnv* env, const IRExpr* e, IREndness IEndianess )
4494 {
4495    HReg r = iselFp128Expr_wrk( env, e, IEndianess );
4496    vassert(hregClass(r) == HRcVec128);
4497    vassert(hregIsVirtual(r));
4498    return r;
4499 }
4500 
4501 /* DO NOT CALL THIS DIRECTLY */
iselFp128Expr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4502 static HReg iselFp128Expr_wrk( ISelEnv* env, const IRExpr* e,
4503                                IREndness IEndianess)
4504 {
4505    Bool mode64 = env->mode64;
4506    PPCFpOp fpop = Pfp_INVALID;
4507    IRType  ty = typeOfIRExpr(env->type_env,e);
4508 
4509    vassert(e);
4510    vassert( ty == Ity_F128 );
4511 
4512    /* read 128-bit IRTemp */
4513    if (e->tag == Iex_RdTmp) {
4514       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
4515    }
4516 
4517   if (e->tag == Iex_Get) {
4518       /* Guest state vectors are 16byte aligned,
4519          so don't need to worry here */
4520       HReg dst = newVRegV(env);
4521 
4522       addInstr(env,
4523                PPCInstr_AvLdSt( True/*load*/, 16, dst,
4524                                 PPCAMode_IR( e->Iex.Get.offset,
4525                                              GuestStatePtr(mode64) )));
4526       return dst;
4527    }
4528 
4529    if (e->tag == Iex_Unop) {
4530       switch (e->Iex.Unop.op) {
4531       case Iop_TruncF128toI64S:
4532          fpop = Pfp_TRUNCFPQTOISD; goto do_Un_F128;
4533       case Iop_TruncF128toI32S:
4534          fpop = Pfp_TRUNCFPQTOISW; goto do_Un_F128;
4535       case Iop_TruncF128toI64U:
4536          fpop = Pfp_TRUNCFPQTOIUD; goto do_Un_F128;
4537       case Iop_TruncF128toI32U:
4538          fpop = Pfp_TRUNCFPQTOIUW; goto do_Un_F128;
4539 
4540       do_Un_F128: {
4541          HReg r_dst = newVRegV(env);
4542          HReg r_src = iselFp128Expr(env, e->Iex.Unop.arg, IEndianess);
4543          addInstr(env, PPCInstr_Fp128Unary(fpop, r_dst, r_src));
4544          return r_dst;
4545       }
4546 
4547       case Iop_F64toF128: {
4548          fpop = Pfp_FPDTOQ;
4549          HReg r_dst = newVRegV(env);
4550          HReg r_src = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
4551          HReg v128tmp = newVRegV(env);
4552          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4553 
4554          /* value is in 64-bit float reg, need to move to 128-bit vector reg */
4555          sub_from_sp( env, 16 );
4556          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, r_src, zero_r1));
4557          addInstr(env, PPCInstr_AvLdSt(True/*load*/, 16, v128tmp, zero_r1));
4558          add_to_sp( env, 16 );
4559 
4560          addInstr(env, PPCInstr_Fp128Unary(fpop, r_dst, v128tmp));
4561          return r_dst;
4562       }
4563 
4564       case Iop_I64StoF128:
4565          fpop = Pfp_IDSTOQ; goto do_Un_int_F128;
4566       case Iop_I64UtoF128:
4567          fpop = Pfp_IDUTOQ; goto do_Un_int_F128;
4568 
4569       do_Un_int_F128: {
4570          HReg r_dst = newVRegV(env);
4571          HReg tmp = newVRegV(env);
4572          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
4573          PPCAMode *am_offhi, *am_offlo;
4574          HReg r_aligned16;
4575 
4576          /* source is in a 64-bit integer reg, move to 128-bit float reg
4577           * do this via the stack (easy, convenient, etc).
4578           */
4579          sub_from_sp( env, 32 );        // Move SP down
4580 
4581          /* Get a quadword aligned address within our stack space */
4582          r_aligned16 = get_sp_aligned16( env );
4583 
4584          am_offlo  = PPCAMode_IR( 0,  r_aligned16 );
4585          am_offhi  = PPCAMode_IR( 8,  r_aligned16 );
4586 
4587          /* Inst only uses the upper 64-bit of the source */
4588          addInstr(env, PPCInstr_Load(8, r_src, am_offhi, mode64));
4589 
4590          /* Fetch result back from stack. */
4591          addInstr(env, PPCInstr_AvLdSt(True/*load*/, 16, tmp, am_offlo));
4592 
4593          add_to_sp( env, 32 );          // Reset SP
4594 
4595          addInstr(env, PPCInstr_Fp128Unary(fpop, r_dst, tmp));
4596          return r_dst;
4597       }
4598 
4599       default:
4600          break;
4601       } /* switch (e->Iex.Unop.op) */
4602    } /* if (e->tag == Iex_Unop) */
4603 
4604    if (e->tag == Iex_Binop) {
4605       switch (e->Iex.Binop.op) {
4606 
4607       case Iop_F64HLtoF128:
4608          {
4609             HReg dst    = newVRegV(env);
4610             HReg r_src_hi = iselDblExpr(env, e->Iex.Binop.arg1, IEndianess);
4611             HReg r_src_lo = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
4612             PPCAMode *am_offhi, *am_offlo;
4613             HReg r_aligned16;
4614 
4615             /* do this via the stack (easy, convenient, etc) */
4616             sub_from_sp( env, 16 );        // Move SP down
4617 
4618             /* Get a quadword aligned address within our stack space */
4619             r_aligned16 = get_sp_aligned16( env );
4620 
4621             am_offlo  = PPCAMode_IR( 0,  r_aligned16 );
4622             am_offhi  = PPCAMode_IR( 8,  r_aligned16 );
4623 
4624             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8,
4625                                           r_src_lo, am_offlo));
4626             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8,
4627                                           r_src_hi, am_offhi));
4628 
4629             /* Fetch result back from stack. */
4630             addInstr(env, PPCInstr_AvLdSt(True/*load*/, 16,
4631                                           dst, am_offlo));
4632 
4633             add_to_sp( env, 16 );          // Reset SP
4634             return dst;
4635          }
4636       case Iop_F128toI128S:
4637          {
4638             HReg dst    = newVRegV(env);
4639             HReg r_src  = iselFp128Expr(env, e->Iex.Binop.arg2, IEndianess);
4640             PPCRI* rm = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
4641             /* Note: rm is a set of three bit fields that specify the
4642              * rounding mode and which of the two instructions to issue.
4643              */
4644             addInstr(env, PPCInstr_AvBinaryInt(Pav_F128toI128S, dst,
4645                                                r_src, rm));
4646             return dst;
4647          }
4648       case Iop_RndF128:
4649          {
4650             HReg dst    = newVRegV(env);
4651             HReg r_src  = iselFp128Expr(env, e->Iex.Binop.arg2, IEndianess);
4652             PPCRI* rm = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
4653             /* Note: rm is a set of three bit fields that specify the
4654              * rounding mode and which of the two instructions to issue.
4655              */
4656             addInstr(env, PPCInstr_AvBinaryInt(Pav_ROUNDFPQ, dst,
4657                                                r_src, rm));
4658             return dst;
4659          }
4660       case Iop_SqrtF128:
4661          if (FPU_rounding_mode_isOdd(e->Iex.Binop.arg1)) {
4662             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4663             fpop = Pfp_FPSQRTQRNDODD;
4664             goto do_Bin_F128;
4665          } else {
4666             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4667             fpop = Pfp_FPSQRTQ;
4668             goto do_Bin_F128;
4669          }
4670       case Iop_F128toF32:
4671          if (FPU_rounding_mode_isOdd(e->Iex.Binop.arg1)) {
4672             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4673             fpop = Pfp_FPQTOWRNDODD;
4674             goto do_Bin_F128;
4675          } else {
4676             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4677             fpop = Pfp_FPQTOW;
4678             goto do_Bin_F128;
4679          }
4680       do_Bin_F128: {
4681          HReg r_dst = newVRegV(env);
4682          HReg r_src = iselFp128Expr(env, e->Iex.Binop.arg2, IEndianess);
4683          addInstr(env, PPCInstr_Fp128Unary(fpop, r_dst, r_src));
4684          return r_dst;
4685       }
4686 
4687       default:
4688          break;
4689       } /* switch (e->Iex.Binop.op) */
4690    } /* if (e->tag == Iex_Binop) */
4691 
4692    if (e->tag == Iex_Triop) {
4693       IRTriop *triop = e->Iex.Triop.details;
4694 
4695       switch (triop->op) {
4696       case Iop_AddF128:
4697          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4698             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4699             fpop = Pfp_FPADDQRNDODD; goto do_Tri_F128;
4700          } else {
4701             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4702             fpop = Pfp_FPADDQ; goto do_Tri_F128;
4703          }
4704       case Iop_SubF128:
4705          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4706             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4707             fpop = Pfp_FPSUBQRNDODD; goto do_Tri_F128;
4708          } else {
4709             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4710             fpop = Pfp_FPSUBQ; goto do_Tri_F128;
4711          }
4712       case Iop_MulF128:
4713          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4714             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4715             fpop = Pfp_FPMULQRNDODD; goto do_Tri_F128;
4716          } else {
4717             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4718             fpop = Pfp_FPMULQ; goto do_Tri_F128;
4719          }
4720       case Iop_DivF128:
4721          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4722             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4723             fpop = Pfp_FPDIVQRNDODD; goto do_Tri_F128;
4724          } else {
4725             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4726             fpop = Pfp_FPDIVQ; goto do_Tri_F128;
4727          }
4728       case Iop_MAddF128:
4729          if (FPU_rounding_mode_isOdd(triop->arg1)) {
4730             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4731             fpop = Pfp_FPMULADDQRNDODD; goto do_Tri_F128;
4732          } else {
4733             set_FPU_rounding_mode( env, triop->arg1, IEndianess );
4734             fpop = Pfp_FPMULADDQ; goto do_Tri_F128;
4735          }
4736 
4737    do_Tri_F128: {
4738          HReg r_dst  = newVRegV(env);
4739          HReg r_srcL = iselFp128Expr(env, triop->arg2, IEndianess);
4740          HReg r_srcR = iselFp128Expr(env, triop->arg3, IEndianess);
4741 
4742          addInstr(env, PPCInstr_Fp128Binary(fpop, r_dst, r_srcL, r_srcR));
4743          return r_dst;
4744       }
4745 
4746       default:
4747          break;
4748       } /* switch (e->Iex.Triop.op) */
4749 
4750    } /* if (e->tag == Iex_Trinop) */
4751 
4752    if (e->tag == Iex_Qop) {
4753       IRQop *qop = e->Iex.Qop.details;
4754 
4755       switch (qop->op) {
4756       case Iop_MAddF128:
4757          if (FPU_rounding_mode_isOdd(qop->arg1)) {
4758             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4759             fpop = Pfp_FPMULADDQRNDODD; goto do_Quad_F128;
4760          } else {
4761             set_FPU_rounding_mode( env, qop->arg1, IEndianess );
4762             fpop = Pfp_FPMULADDQ; goto do_Quad_F128;
4763          }
4764       case Iop_MSubF128:
4765          if (FPU_rounding_mode_isOdd(qop->arg1)) {
4766             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4767             fpop = Pfp_FPMULSUBQRNDODD; goto do_Quad_F128;
4768          } else {
4769             set_FPU_rounding_mode( env, qop->arg1, IEndianess );
4770             fpop = Pfp_FPMULSUBQ; goto do_Quad_F128;
4771          }
4772       case Iop_NegMAddF128:
4773          if (FPU_rounding_mode_isOdd(qop->arg1)) {
4774             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4775             fpop = Pfp_FPNEGMULADDQRNDODD; goto do_Quad_F128;
4776          } else {
4777             set_FPU_rounding_mode( env, qop->arg1, IEndianess );
4778             fpop = Pfp_FPNEGMULADDQ; goto do_Quad_F128;
4779          }
4780       case Iop_NegMSubF128:
4781          if (FPU_rounding_mode_isOdd(qop->arg1)) {
4782             /* use rounding mode specified by RN. Issue inst with R0 = 0 */
4783             fpop = Pfp_FPNEGMULSUBQRNDODD; goto do_Quad_F128;
4784          } else {
4785             set_FPU_rounding_mode( env, qop->arg1, IEndianess );
4786             fpop = Pfp_FPNEGMULSUBQ; goto do_Quad_F128;
4787          }
4788 
4789       do_Quad_F128: {
4790          HReg r_dst = iselFp128Expr(env, qop->arg3,
4791                                     IEndianess);
4792          HReg r_srcL = iselFp128Expr(env, qop->arg2,
4793                                      IEndianess);
4794          HReg r_srcR = iselFp128Expr(env, qop->arg4,
4795                                      IEndianess);
4796 
4797          addInstr(env, PPCInstr_Fp128Trinary(fpop, r_dst, r_srcL, r_srcR));
4798          return r_dst;
4799          }
4800 
4801       default:
4802          break;
4803       }
4804    }   /* if (e->tag == Iex_Qop) */
4805 
4806    ppIRExpr( e );
4807    vpanic( "iselFp128Expr(ppc64)" );
4808 }
4809 
iselDfp64Expr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4810 static HReg iselDfp64Expr(ISelEnv* env, const IRExpr* e, IREndness IEndianess)
4811 {
4812    HReg r = iselDfp64Expr_wrk( env, e, IEndianess );
4813    vassert(hregClass(r) == HRcFlt64);
4814    vassert( hregIsVirtual(r) );
4815    return r;
4816 }
4817 
4818 /* DO NOT CALL THIS DIRECTLY */
iselDfp64Expr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)4819 static HReg iselDfp64Expr_wrk(ISelEnv* env, const IRExpr* e,
4820                               IREndness IEndianess)
4821 {
4822    Bool mode64 = env->mode64;
4823    IRType ty = typeOfIRExpr( env->type_env, e );
4824    HReg r_dstHi, r_dstLo;
4825 
4826    vassert( e );
4827    vassert( ty == Ity_D64 );
4828 
4829    if (e->tag == Iex_RdTmp) {
4830       return lookupIRTemp( env, e->Iex.RdTmp.tmp );
4831    }
4832 
4833    /* --------- GET --------- */
4834    if (e->tag == Iex_Get) {
4835       HReg r_dst = newVRegF( env );
4836       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
4837                                        GuestStatePtr(mode64) );
4838       addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
4839       return r_dst;
4840    }
4841 
4842    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
4843       PPCAMode* am_addr;
4844       HReg r_dst = newVRegF(env);
4845       vassert(e->Iex.Load.ty == Ity_D64);
4846       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D64/*xfer*/,
4847                                    IEndianess);
4848       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
4849       return r_dst;
4850    }
4851 
4852    /* --------- OPS --------- */
4853    if (e->tag == Iex_Qop) {
4854       HReg r_dst = newVRegF( env );
4855       return r_dst;
4856    }
4857 
4858    if (e->tag == Iex_Unop) {
4859       HReg fr_dst = newVRegF(env);
4860       switch (e->Iex.Unop.op) {
4861       case Iop_ReinterpI64asD64: {
4862          /* Given an I64, produce an IEEE754 DFP with the same
4863                bit pattern. */
4864          if (!mode64) {
4865             HReg r_srcHi, r_srcLo;
4866             iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg,
4867                            IEndianess);
4868             return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
4869          } else {
4870             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
4871             return mk_LoadR64toFPR( env, r_src );
4872          }
4873       }
4874       case Iop_D32toD64: {
4875          HReg fr_src = iselDfp32Expr(env, e->Iex.Unop.arg, IEndianess);
4876          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
4877          return fr_dst;
4878       }
4879       case Iop_D128HItoD64:
4880          iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg,
4881                          IEndianess );
4882          return r_dstHi;
4883       case Iop_D128LOtoD64:
4884          iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg,
4885                          IEndianess );
4886          return r_dstLo;
4887       case Iop_InsertExpD64: {
4888          HReg fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1, IEndianess);
4889          HReg fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
4890 
4891          addInstr(env, PPCInstr_Dfp64Binary(Pfp_DIEX, fr_dst, fr_srcL,
4892 					    fr_srcR));
4893          return fr_dst;
4894        }
4895       default:
4896          vex_printf( "ERROR: iselDfp64Expr_wrk, UNKNOWN unop case %d\n",
4897                      (Int)e->Iex.Unop.op );
4898       }
4899    }
4900 
4901    if (e->tag == Iex_Binop) {
4902       PPCFpOp fpop = Pfp_INVALID;
4903       HReg fr_dst = newVRegF(env);
4904 
4905       switch (e->Iex.Binop.op) {
4906       case Iop_D128toD64:     fpop = Pfp_DRDPQ;  break;
4907       case Iop_D64toD32:      fpop = Pfp_DRSP;   break;
4908       case Iop_I64StoD64:     fpop = Pfp_DCFFIX; break;
4909       case Iop_RoundD64toInt: fpop = Pfp_DRINTN; break;
4910       default: break;
4911       }
4912       if (fpop == Pfp_DRDPQ) {
4913          HReg r_srcHi = newVRegF(env);
4914          HReg r_srcLo = newVRegF(env);
4915 
4916          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4917          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
4918                         IEndianess);
4919          addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
4920          return fr_dst;
4921 
4922       } else if (fpop == Pfp_DRINTN) {
4923          HReg fr_src = newVRegF(env);
4924          PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
4925 
4926          /* NOTE, this IOP takes a DFP value and rounds to the
4927           * neares floating point integer value, i.e. fractional part
4928           * is zero.  The result is a decimal floating point number.
4929           * the INT in the name is a bit misleading.
4930           */
4931          fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
4932          addInstr(env, PPCInstr_DfpRound(fr_dst, fr_src, r_rmc));
4933          return fr_dst;
4934 
4935       } else if (fpop == Pfp_DRSP) {
4936          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
4937          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4938          addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
4939          return fr_dst;
4940 
4941       } else if (fpop == Pfp_DCFFIX) {
4942          HReg fr_src = newVRegF(env);
4943          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4944 
4945          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
4946          sub_from_sp( env, 16 );
4947 
4948          // put the I64 value into a floating point register
4949          if (mode64) {
4950            HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
4951 
4952            addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
4953          } else {
4954             HReg tmpHi, tmpLo;
4955             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
4956 
4957             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Binop.arg2,
4958                           IEndianess);
4959             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
4960             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
4961          }
4962 
4963          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8,  fr_src, zero_r1));
4964          addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
4965          add_to_sp( env, 16 );
4966          return fr_dst;
4967       }
4968 
4969       switch (e->Iex.Binop.op) {
4970       /* shift instructions D64, I32 -> D64 */
4971       case Iop_ShlD64: fpop = Pfp_DSCLI; break;
4972       case Iop_ShrD64: fpop = Pfp_DSCRI; break;
4973       default: break;
4974       }
4975       if (fpop != Pfp_INVALID) {
4976          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg1, IEndianess);
4977          PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
4978 
4979          /* shift value must be an immediate value */
4980          vassert(shift->tag == Pri_Imm);
4981 
4982          addInstr(env, PPCInstr_DfpShift(fpop, fr_dst, fr_src, shift));
4983          return fr_dst;
4984       }
4985 
4986       switch (e->Iex.Binop.op) {
4987       case Iop_InsertExpD64:
4988          fpop = Pfp_DIEX;
4989          break;
4990       default: 	break;
4991       }
4992       if (fpop != Pfp_INVALID) {
4993          HReg fr_srcL = newVRegF(env);
4994          HReg fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
4995          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4996          sub_from_sp( env, 16 );
4997 
4998          if (env->mode64) {
4999             // put the I64 value into a floating point reg
5000             HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
5001 
5002             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
5003          } else {
5004             // put the I64 register pair into a floating point reg
5005             HReg tmpHi;
5006             HReg tmpLo;
5007             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
5008 
5009             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Binop.arg1,
5010                           IEndianess);
5011             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*!mode64*/));
5012             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*!mode64*/));
5013          }
5014          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_srcL, zero_r1));
5015          addInstr(env, PPCInstr_Dfp64Binary(fpop, fr_dst, fr_srcL,
5016                                             fr_srcR));
5017          add_to_sp( env, 16 );
5018          return fr_dst;
5019       }
5020    }
5021 
5022    if (e->tag == Iex_Triop) {
5023       IRTriop *triop = e->Iex.Triop.details;
5024       PPCFpOp fpop = Pfp_INVALID;
5025 
5026       switch (triop->op) {
5027       case Iop_AddD64:
5028          fpop = Pfp_DFPADD;
5029          break;
5030       case Iop_SubD64:
5031          fpop = Pfp_DFPSUB;
5032          break;
5033       case Iop_MulD64:
5034          fpop = Pfp_DFPMUL;
5035          break;
5036       case Iop_DivD64:
5037          fpop = Pfp_DFPDIV;
5038          break;
5039       default:
5040          break;
5041       }
5042       if (fpop != Pfp_INVALID) {
5043          HReg r_dst = newVRegF( env );
5044          HReg r_srcL = iselDfp64Expr( env, triop->arg2, IEndianess );
5045          HReg r_srcR = iselDfp64Expr( env, triop->arg3, IEndianess );
5046 
5047          set_FPU_DFP_rounding_mode( env, triop->arg1, IEndianess );
5048          addInstr( env, PPCInstr_Dfp64Binary( fpop, r_dst, r_srcL, r_srcR ) );
5049          return r_dst;
5050       }
5051 
5052       switch (triop->op) {
5053       case Iop_QuantizeD64:          fpop = Pfp_DQUA;  break;
5054       case Iop_SignificanceRoundD64: fpop = Pfp_RRDTR; break;
5055       default: break;
5056       }
5057       if (fpop == Pfp_DQUA) {
5058          HReg r_dst = newVRegF(env);
5059          HReg r_srcL = iselDfp64Expr(env, triop->arg2, IEndianess);
5060          HReg r_srcR = iselDfp64Expr(env, triop->arg3, IEndianess);
5061          PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1, IEndianess);
5062          addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR,
5063                                             rmc));
5064          return r_dst;
5065 
5066       } else if (fpop == Pfp_RRDTR) {
5067          HReg r_dst = newVRegF(env);
5068          HReg r_srcL = newVRegF(env);
5069          HReg r_srcR = iselDfp64Expr(env, triop->arg3, IEndianess);
5070          PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1, IEndianess);
5071          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5072          HReg i8_val = iselWordExpr_R(env, triop->arg2, IEndianess);
5073 
5074          /* Move I8 to float register to issue instruction */
5075          sub_from_sp( env, 16 );
5076          if (mode64)
5077             addInstr(env, PPCInstr_Store(8, zero_r1, i8_val, True/*mode64*/));
5078          else
5079             addInstr(env, PPCInstr_Store(4, zero_r1, i8_val, False/*mode32*/));
5080 
5081          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_srcL, zero_r1));
5082          add_to_sp( env, 16 );
5083 
5084          // will set TE and RMC when issuing instruction
5085          addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR, rmc));
5086          return r_dst;
5087       }
5088    }
5089 
5090    ppIRExpr( e );
5091    vpanic( "iselDfp64Expr_wrk(ppc)" );
5092 }
5093 
iselDfp128Expr(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)5094 static void iselDfp128Expr(HReg* rHi, HReg* rLo, ISelEnv* env, const IRExpr* e,
5095                            IREndness IEndianess)
5096 {
5097    iselDfp128Expr_wrk( rHi, rLo, env, e, IEndianess );
5098    vassert( hregIsVirtual(*rHi) );
5099    vassert( hregIsVirtual(*rLo) );
5100 }
5101 
5102 /* DO NOT CALL THIS DIRECTLY */
iselDfp128Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,const IRExpr * e,IREndness IEndianess)5103 static void iselDfp128Expr_wrk(HReg* rHi, HReg *rLo, ISelEnv* env,
5104                                const IRExpr* e, IREndness IEndianess)
5105 {
5106    vassert( e );
5107    vassert( typeOfIRExpr(env->type_env,e) == Ity_D128 );
5108 
5109    /* read 128-bit IRTemp */
5110    if (e->tag == Iex_RdTmp) {
5111       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp );
5112       return;
5113    }
5114 
5115    if (e->tag == Iex_Unop) {
5116       HReg r_dstHi = newVRegF(env);
5117       HReg r_dstLo = newVRegF(env);
5118 
5119       if (e->Iex.Unop.op == Iop_I64StoD128) {
5120          HReg fr_src = newVRegF(env);
5121          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5122 
5123          // put the I64 value into a floating point reg
5124          if (env->mode64) {
5125             HReg tmp   = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
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.Unop.arg,
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_DfpI64StoD128(Pfp_DCFFIXQ, r_dstHi, r_dstLo,
5139                                               fr_src));
5140       }
5141 
5142       if (e->Iex.Unop.op == Iop_D64toD128) {
5143          HReg r_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
5144 
5145          /* Source is 64bit, result is 128 bit.  High 64bit source arg,
5146           * is ignored by the instruction.  Set high arg to r_src just
5147           * to meet the vassert tests.
5148           */
5149          addInstr(env, PPCInstr_Dfp128Unary(Pfp_DCTQPQ, r_dstHi, r_dstLo,
5150                                             r_src, r_src));
5151       }
5152       *rHi = r_dstHi;
5153       *rLo = r_dstLo;
5154       return;
5155    }
5156 
5157    /* --------- OPS --------- */
5158    if (e->tag == Iex_Binop) {
5159       HReg r_srcHi;
5160       HReg r_srcLo;
5161 
5162       switch (e->Iex.Binop.op) {
5163       case Iop_D64HLtoD128:
5164          r_srcHi = iselDfp64Expr( env, e->Iex.Binop.arg1, IEndianess );
5165          r_srcLo = iselDfp64Expr( env, e->Iex.Binop.arg2, IEndianess );
5166          *rHi = r_srcHi;
5167          *rLo = r_srcLo;
5168          return;
5169          break;
5170       case Iop_D128toD64: {
5171          PPCFpOp fpop = Pfp_DRDPQ;
5172          HReg fr_dst  = newVRegF(env);
5173 
5174          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
5175          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
5176                         IEndianess);
5177          addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
5178 
5179          /* Need to meet the interface spec but the result is
5180           * just 64-bits so send the result back in both halfs.
5181           */
5182          *rHi = fr_dst;
5183          *rLo = fr_dst;
5184          return;
5185       }
5186       case Iop_ShlD128:
5187       case Iop_ShrD128: {
5188          HReg fr_dst_hi = newVRegF(env);
5189          HReg fr_dst_lo = newVRegF(env);
5190          PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
5191          PPCFpOp fpop = Pfp_DSCLIQ;  /* fix later if necessary */
5192 
5193          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1,
5194                         IEndianess);
5195 
5196          if (e->Iex.Binop.op == Iop_ShrD128)
5197             fpop = Pfp_DSCRIQ;
5198 
5199          addInstr(env, PPCInstr_DfpShift128(fpop, fr_dst_hi, fr_dst_lo,
5200                                             r_srcHi, r_srcLo, shift));
5201 
5202          *rHi = fr_dst_hi;
5203          *rLo = fr_dst_lo;
5204          return;
5205       }
5206       case Iop_RoundD128toInt: {
5207          HReg r_dstHi = newVRegF(env);
5208          HReg r_dstLo = newVRegF(env);
5209          PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
5210 
5211          // will set R and RMC when issuing instruction
5212          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
5213                         IEndianess);
5214 
5215          addInstr(env, PPCInstr_DfpRound128(r_dstHi, r_dstLo,
5216                                             r_srcHi, r_srcLo, r_rmc));
5217          *rHi = r_dstHi;
5218          *rLo = r_dstLo;
5219          return;
5220       }
5221       case Iop_InsertExpD128: {
5222          HReg r_dstHi = newVRegF(env);
5223          HReg r_dstLo = newVRegF(env);
5224          HReg r_srcL  = newVRegF(env);
5225          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5226          r_srcHi = newVRegF(env);
5227          r_srcLo = newVRegF(env);
5228 
5229          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
5230                         IEndianess);
5231 
5232          /* Move I64 to float register to issue instruction */
5233          if (env->mode64) {
5234             HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
5235             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
5236          } else {
5237             HReg tmpHi, tmpLo;
5238             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
5239 
5240             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg,
5241                           IEndianess);
5242             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
5243             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
5244          }
5245 
5246          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_srcL, zero_r1));
5247          addInstr(env, PPCInstr_InsertExpD128(Pfp_DIEXQ,
5248                                               r_dstHi, r_dstLo,
5249                                               r_srcL, r_srcHi, r_srcLo));
5250          *rHi = r_dstHi;
5251          *rLo = r_dstLo;
5252          return;
5253       }
5254       default:
5255          vex_printf( "ERROR: iselDfp128Expr_wrk, UNKNOWN binop case %d\n",
5256                      (Int)e->Iex.Binop.op );
5257          break;
5258       }
5259    }
5260 
5261    if (e->tag == Iex_Triop) {
5262       IRTriop *triop = e->Iex.Triop.details;
5263       PPCFpOp fpop = Pfp_INVALID;
5264       HReg r_dstHi = newVRegF(env);
5265       HReg r_dstLo = newVRegF(env);
5266 
5267       switch (triop->op) {
5268       case Iop_AddD128:
5269          fpop = Pfp_DFPADDQ;
5270          break;
5271       case Iop_SubD128:
5272          fpop = Pfp_DFPSUBQ;
5273          break;
5274       case Iop_MulD128:
5275          fpop = Pfp_DFPMULQ;
5276          break;
5277       case Iop_DivD128:
5278          fpop = Pfp_DFPDIVQ;
5279          break;
5280       default:
5281          break;
5282       }
5283 
5284       if (fpop != Pfp_INVALID) {
5285          HReg r_srcRHi = newVRegV( env );
5286          HReg r_srcRLo = newVRegV( env );
5287 
5288          /* dst will be used to pass in the left operand and get the result. */
5289          iselDfp128Expr( &r_dstHi, &r_dstLo, env, triop->arg2, IEndianess );
5290          iselDfp128Expr( &r_srcRHi, &r_srcRLo, env, triop->arg3, IEndianess );
5291          set_FPU_DFP_rounding_mode( env, triop->arg1, IEndianess );
5292          addInstr( env,
5293                    PPCInstr_Dfp128Binary( fpop, r_dstHi, r_dstLo,
5294                                           r_srcRHi, r_srcRLo ) );
5295          *rHi = r_dstHi;
5296          *rLo = r_dstLo;
5297          return;
5298       }
5299       switch (triop->op) {
5300       case Iop_QuantizeD128:          fpop = Pfp_DQUAQ;  break;
5301       case Iop_SignificanceRoundD128: fpop = Pfp_DRRNDQ; break;
5302       default: break;
5303       }
5304       if (fpop == Pfp_DQUAQ) {
5305          HReg r_srcHi = newVRegF(env);
5306          HReg r_srcLo = newVRegF(env);
5307          PPCRI* rmc = iselWordExpr_RI(env, triop->arg1, IEndianess);
5308 
5309          /* dst will be used to pass in the left operand and get the result */
5310          iselDfp128Expr(&r_dstHi, &r_dstLo, env, triop->arg2, IEndianess);
5311          iselDfp128Expr(&r_srcHi, &r_srcLo, env, triop->arg3, IEndianess);
5312 
5313          // will set RMC when issuing instruction
5314          addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
5315                                                r_srcHi, r_srcLo, rmc));
5316         *rHi = r_dstHi;
5317         *rLo = r_dstLo;
5318          return;
5319 
5320       } else if (fpop == Pfp_DRRNDQ) {
5321          HReg r_srcHi = newVRegF(env);
5322          HReg r_srcLo = newVRegF(env);
5323          PPCRI* rmc = iselWordExpr_RI(env, triop->arg1, IEndianess);
5324          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
5325          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
5326          HReg i8_val = iselWordExpr_R(env, triop->arg2, IEndianess);
5327          HReg r_zero = newVRegI( env );
5328 
5329          iselDfp128Expr(&r_srcHi, &r_srcLo, env, triop->arg3, IEndianess);
5330 
5331          /* dst will be used to pass in the left operand and get the result */
5332          /* Move I8 to float register to issue instruction.  Note, the
5333           * instruction only looks at the bottom 6 bits so we really don't
5334           * have to clear the upper bits since the iselWordExpr_R sets the
5335           * bottom 8-bits.
5336           */
5337          sub_from_sp( env, 16 );
5338 
5339          if (env->mode64)
5340             addInstr(env, PPCInstr_Store(4, four_r1, i8_val, True/*mode64*/));
5341          else
5342             addInstr(env, PPCInstr_Store(4, four_r1, i8_val, False/*mode32*/));
5343 
5344          /* Have to write to the upper bits to ensure they have been
5345           * initialized. The instruction ignores all but the lower 6-bits.
5346           */
5347          addInstr( env, PPCInstr_LI( r_zero, 0, env->mode64 ) );
5348          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dstHi, zero_r1));
5349          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dstLo, zero_r1));
5350 
5351          add_to_sp( env, 16 );
5352 
5353          // will set RMC when issuing instruction
5354          addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
5355                                                r_srcHi, r_srcLo, rmc));
5356          *rHi = r_dstHi;
5357          *rLo = r_dstLo;
5358          return;
5359       }
5360  }
5361 
5362    ppIRExpr( e );
5363    vpanic( "iselDfp128Expr(ppc64)" );
5364 }
5365 
5366 
5367 /*---------------------------------------------------------*/
5368 /*--- ISEL: SIMD (Vector) expressions, 128 bit.         ---*/
5369 /*---------------------------------------------------------*/
5370 
iselVecExpr(ISelEnv * env,const IRExpr * e,IREndness IEndianess)5371 static HReg iselVecExpr ( ISelEnv* env, const IRExpr* e, IREndness IEndianess )
5372 {
5373    HReg r = iselVecExpr_wrk( env, e, IEndianess );
5374 #  if 0
5375    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
5376 #  endif
5377    vassert(hregClass(r) == HRcVec128);
5378    vassert(hregIsVirtual(r));
5379    return r;
5380 }
5381 
5382 /* DO NOT CALL THIS DIRECTLY */
iselVecExpr_wrk(ISelEnv * env,const IRExpr * e,IREndness IEndianess)5383 static HReg iselVecExpr_wrk ( ISelEnv* env, const IRExpr* e,
5384                               IREndness IEndianess )
5385 {
5386    Bool mode64 = env->mode64;
5387    PPCAvOp op = Pav_INVALID;
5388    PPCAvFpOp fpop = Pavfp_INVALID;
5389    IRType  ty = typeOfIRExpr(env->type_env,e);
5390    vassert(e);
5391    vassert(ty == Ity_V128);
5392 
5393    if (e->tag == Iex_RdTmp) {
5394       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
5395    }
5396 
5397    if (e->tag == Iex_Get) {
5398       /* Guest state vectors are 16byte aligned,
5399          so don't need to worry here */
5400       HReg dst = newVRegV(env);
5401       addInstr(env,
5402                PPCInstr_AvLdSt( True/*load*/, 16, dst,
5403                                 PPCAMode_IR( e->Iex.Get.offset,
5404                                              GuestStatePtr(mode64) )));
5405       return dst;
5406    }
5407 
5408    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
5409       /* Need to be able to do V128 unaligned loads. The BE unaligned load
5410        * can be accomplised using the following code sequece from the ISA.
5411        * It uses the lvx instruction that does two aligned loads and then
5412        * permute the data to store the required data as if it had been an
5413        * unaligned load.
5414        *
5415        *   lvx  Vhi,0,Rb        # load MSQ, using the unaligned address in Rb
5416        *   lvsl Vp, 0,Rb        # Set permute control vector
5417        *   addi Rb,Rb,15        # Address of LSQ
5418        *   lvx  Vlo,0,Rb        # load LSQ
5419        *   vperm Vt,Vhi,Vlo,Vp  # align the data as requested
5420        */
5421 
5422       HReg Vhi   = newVRegV(env);
5423       HReg Vlo   = newVRegV(env);
5424       HReg Vp    = newVRegV(env);
5425       HReg v_dst = newVRegV(env);
5426       HReg rB;
5427       HReg rB_plus_15 = newVRegI(env);
5428 
5429       vassert(e->Iex.Load.ty == Ity_V128);
5430       rB = iselWordExpr_R( env, e->Iex.Load.addr, IEndianess );
5431 
5432       // lvx  Vhi, 0, Rb
5433       addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, Vhi,
5434                                      PPCAMode_IR(0, rB)) );
5435 
5436       if (IEndianess == Iend_LE)
5437          // lvsr Vp, 0, Rb
5438          addInstr(env, PPCInstr_AvSh( False/*right shift*/, Vp,
5439                                       PPCAMode_IR(0, rB)) );
5440       else
5441          // lvsl Vp, 0, Rb
5442          addInstr(env, PPCInstr_AvSh( True/*left shift*/, Vp,
5443                                       PPCAMode_IR(0, rB)) );
5444 
5445       // addi Rb_plus_15, Rb, 15
5446       addInstr(env, PPCInstr_Alu( Palu_ADD, rB_plus_15,
5447                                   rB, PPCRH_Imm(True, toUShort(15))) );
5448 
5449       // lvx  Vlo, 0, Rb_plus_15
5450       addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, Vlo,
5451                                      PPCAMode_IR(0, rB_plus_15)) );
5452 
5453       if (IEndianess == Iend_LE)
5454          // vperm Vt, Vhi, Vlo, Vp
5455          addInstr(env, PPCInstr_AvPerm( v_dst, Vlo, Vhi, Vp ));
5456       else
5457          // vperm Vt, Vhi, Vlo, Vp
5458          addInstr(env, PPCInstr_AvPerm( v_dst, Vhi, Vlo, Vp ));
5459 
5460       return v_dst;
5461    }
5462 
5463    if (e->tag == Iex_Unop) {
5464       switch (e->Iex.Unop.op) {
5465 
5466       case Iop_F16toF64x2:
5467          {
5468             HReg dst = newVRegV(env);
5469             HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5470             /* Note: PPC only coverts the 16-bt value in the upper word
5471              *       to a 64-bit value stored in the upper word.  The
5472              *       contents of the lower word is undefined.
5473              */
5474             addInstr(env, PPCInstr_AvUnary(Pav_F16toF64x2, dst, arg));
5475             return dst;
5476          }
5477 
5478       case Iop_F64toF16x2:
5479          {
5480             HReg dst = newVRegV(env);
5481             HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5482             /* Note: PPC only coverts the 64-bt value in the upper 64-bit of V128
5483              * to a 16-bit value stored in the upper 64-bits of the result
5484              * V128.  The contents of the lower 64-bits is undefined.
5485              */
5486             addInstr(env, PPCInstr_AvUnary(Pav_F64toF16x2, dst, arg));
5487             return dst;
5488          }
5489 
5490       case Iop_F16toF32x4:
5491          {
5492             HReg src = newVRegV(env);
5493             HReg dst = newVRegV(env);
5494             HReg arg = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
5495             PPCAMode *am_off0, *am_off8;
5496             HReg r_aligned16;
5497 
5498             vassert(mode64);
5499             /* need to put I64 src into upper 64-bits of vector register,
5500                use stack */
5501             sub_from_sp( env, 32 );     // Move SP down
5502 
5503             /* Get a quadword aligned address within our stack space */
5504             r_aligned16 = get_sp_aligned16( env );
5505             am_off0  = PPCAMode_IR( 0, r_aligned16 );
5506             am_off8  = PPCAMode_IR( 8, r_aligned16 );
5507 
5508             /* Store I64 to stack */
5509 
5510             if (IEndianess == Iend_LE) {
5511                addInstr(env, PPCInstr_Store( 8, am_off8, arg, mode64 ));
5512             } else {
5513                addInstr(env, PPCInstr_Store( 8, am_off0, arg, mode64 ));
5514             }
5515 
5516             /* Fetch new v128 src back from stack. */
5517             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, src, am_off0));
5518 
5519             /* issue instruction */
5520             addInstr(env, PPCInstr_AvUnary(Pav_F16toF32x4, dst, src));
5521             add_to_sp( env, 32 );          // Reset SP
5522 
5523             return dst;
5524          }
5525 
5526       case Iop_F32toF16x4:
5527          {
5528             HReg dst = newVRegI(env);
5529             HReg tmp = newVRegV(env);
5530             HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5531             PPCAMode *am_off0, *am_off8;
5532             HReg r_aligned16;
5533 
5534             /* Instruction returns a V128, the Iop_F32toF16x4 needs to return
5535              * I64.  Move the upper 64-bits from the instruction to an I64 via
5536              * the stack and return it.
5537              */
5538             sub_from_sp( env, 32 );     // Move SP down
5539 
5540             addInstr(env, PPCInstr_AvUnary(Pav_F32toF16x4, tmp, arg));
5541 
5542             /* Get a quadword aligned address within our stack space */
5543             r_aligned16 = get_sp_aligned16( env );
5544             am_off0  = PPCAMode_IR( 0, r_aligned16 );
5545             am_off8  = PPCAMode_IR( 8, r_aligned16 );
5546 
5547             /* Store v128 tmp to stack. */
5548             addInstr(env, PPCInstr_AvLdSt(False/*store*/, 16, tmp, am_off0));
5549 
5550             /* Fetch I64 from stack */
5551             if (IEndianess == Iend_LE) {
5552                addInstr(env, PPCInstr_Load( 8, dst, am_off8, mode64 ));
5553             } else {
5554                addInstr(env, PPCInstr_Load( 8, dst, am_off0, mode64 ));
5555             }
5556 
5557             add_to_sp( env, 32 );          // Reset SP
5558             return dst;
5559          }
5560 
5561       case Iop_NotV128: {
5562          HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5563          HReg dst = newVRegV(env);
5564          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, arg));
5565          return dst;
5566       }
5567 
5568       case Iop_CmpNEZ8x16: {
5569          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5570          HReg zero = newVRegV(env);
5571          HReg dst  = newVRegV(env);
5572          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
5573          addInstr(env, PPCInstr_AvBin8x16(Pav_CMPEQU, dst, arg, zero));
5574          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5575          return dst;
5576       }
5577 
5578       case Iop_CmpNEZ16x8: {
5579          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5580          HReg zero = newVRegV(env);
5581          HReg dst  = newVRegV(env);
5582          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
5583          addInstr(env, PPCInstr_AvBin16x8(Pav_CMPEQU, dst, arg, zero));
5584          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5585          return dst;
5586       }
5587 
5588       case Iop_CmpNEZ32x4: {
5589          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5590          HReg zero = newVRegV(env);
5591          HReg dst  = newVRegV(env);
5592          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
5593          addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, dst, arg, zero));
5594          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5595          return dst;
5596       }
5597 
5598       case Iop_CmpNEZ64x2: {
5599          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5600          HReg zero = newVRegV(env);
5601          HReg dst  = newVRegV(env);
5602          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
5603          addInstr(env, PPCInstr_AvBin64x2(Pav_CMPEQU, dst, arg, zero));
5604          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5605          return dst;
5606       }
5607 
5608       case Iop_RecipEst32Fx4: fpop = Pavfp_RCPF;    goto do_32Fx4_unary;
5609       case Iop_RSqrtEst32Fx4: fpop = Pavfp_RSQRTF;  goto do_32Fx4_unary;
5610       case Iop_I32UtoFx4:     fpop = Pavfp_CVTU2F;  goto do_32Fx4_unary;
5611       case Iop_I32StoFx4:     fpop = Pavfp_CVTS2F;  goto do_32Fx4_unary;
5612       case Iop_QFtoI32Ux4_RZ: fpop = Pavfp_QCVTF2U; goto do_32Fx4_unary;
5613       case Iop_QFtoI32Sx4_RZ: fpop = Pavfp_QCVTF2S; goto do_32Fx4_unary;
5614       case Iop_RoundF32x4_RM: fpop = Pavfp_ROUNDM;  goto do_32Fx4_unary;
5615       case Iop_RoundF32x4_RP: fpop = Pavfp_ROUNDP;  goto do_32Fx4_unary;
5616       case Iop_RoundF32x4_RN: fpop = Pavfp_ROUNDN;  goto do_32Fx4_unary;
5617       case Iop_RoundF32x4_RZ: fpop = Pavfp_ROUNDZ;  goto do_32Fx4_unary;
5618       do_32Fx4_unary:
5619       {
5620          HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5621          HReg dst = newVRegV(env);
5622          addInstr(env, PPCInstr_AvUn32Fx4(fpop, dst, arg));
5623          return dst;
5624       }
5625 
5626       case Iop_32UtoV128: {
5627          HReg r_aligned16, r_zeros;
5628          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
5629          HReg   dst = newVRegV(env);
5630          PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
5631          sub_from_sp( env, 32 );     // Move SP down
5632 
5633          /* Get a quadword aligned address within our stack space */
5634          r_aligned16 = get_sp_aligned16( env );
5635          am_off0  = PPCAMode_IR( 0,  r_aligned16 );
5636          am_off4  = PPCAMode_IR( 4,  r_aligned16 );
5637          am_off8  = PPCAMode_IR( 8,  r_aligned16 );
5638          am_off12 = PPCAMode_IR( 12, r_aligned16 );
5639 
5640          /* Store zeros */
5641          r_zeros = newVRegI(env);
5642          addInstr(env, PPCInstr_LI(r_zeros, 0x0, mode64));
5643          if (IEndianess == Iend_LE)
5644             addInstr(env, PPCInstr_Store( 4, am_off0, r_src, mode64 ));
5645          else
5646             addInstr(env, PPCInstr_Store( 4, am_off0, r_zeros, mode64 ));
5647          addInstr(env, PPCInstr_Store( 4, am_off4, r_zeros, mode64 ));
5648          addInstr(env, PPCInstr_Store( 4, am_off8, r_zeros, mode64 ));
5649 
5650          /* Store r_src in low word of quadword-aligned mem */
5651          if (IEndianess == Iend_LE)
5652             addInstr(env, PPCInstr_Store( 4, am_off12, r_zeros, mode64 ));
5653          else
5654             addInstr(env, PPCInstr_Store( 4, am_off12, r_src, mode64 ));
5655 
5656          /* Load word into low word of quadword vector reg */
5657          if (IEndianess == Iend_LE)
5658             addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off0 ));
5659          else
5660             addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off12 ));
5661 
5662          add_to_sp( env, 32 );       // Reset SP
5663          return dst;
5664       }
5665 
5666       case Iop_Dup8x16:
5667       case Iop_Dup16x8:
5668       case Iop_Dup32x4:
5669          return mk_AvDuplicateRI(env, e->Iex.Unop.arg, IEndianess);
5670 
5671       case Iop_CipherSV128: op = Pav_CIPHERSUBV128; goto do_AvCipherV128Un;
5672       do_AvCipherV128Un: {
5673          HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5674          HReg dst = newVRegV(env);
5675          addInstr(env, PPCInstr_AvCipherV128Unary(op, dst, arg));
5676          return dst;
5677       }
5678 
5679       case Iop_Clz8x16: op = Pav_ZEROCNTBYTE;   goto do_zerocnt;
5680       case Iop_Clz16x8: op = Pav_ZEROCNTHALF;   goto do_zerocnt;
5681       case Iop_Clz32x4: op = Pav_ZEROCNTWORD;   goto do_zerocnt;
5682       case Iop_Clz64x2: op = Pav_ZEROCNTDBL;    goto do_zerocnt;
5683       case Iop_Ctz8x16: op = Pav_TRAILINGZEROCNTBYTE; goto do_zerocnt;
5684       case Iop_Ctz16x8: op = Pav_TRAILINGZEROCNTHALF; goto do_zerocnt;
5685       case Iop_Ctz32x4: op = Pav_TRAILINGZEROCNTWORD; goto do_zerocnt;
5686       case Iop_Ctz64x2: op = Pav_TRAILINGZEROCNTDBL;  goto do_zerocnt;
5687       case Iop_PwBitMtxXpose64x2: op = Pav_BITMTXXPOSE;  goto do_zerocnt;
5688       do_zerocnt:
5689       {
5690         HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5691         HReg dst = newVRegV(env);
5692         addInstr(env, PPCInstr_AvUnary(op, dst, arg));
5693         return dst;
5694       }
5695 
5696       /* BCD Iops */
5697       case Iop_BCD128toI128S:
5698          {
5699             HReg dst  = newVRegV(env);
5700             HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5701             addInstr(env, PPCInstr_AvUnary( Pav_BCD128toI128S, dst, arg ) );
5702             return dst;
5703          }
5704 
5705       case Iop_MulI128by10:       op = Pav_MulI128by10;      goto do_MulI128;
5706       case Iop_MulI128by10Carry:  op = Pav_MulI128by10Carry; goto do_MulI128;
5707       do_MulI128: {
5708             HReg dst = newVRegV(env);
5709             HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
5710             addInstr(env, PPCInstr_AvUnary(op, dst, arg));
5711             return dst;
5712          }
5713 
5714       default:
5715          break;
5716       } /* switch (e->Iex.Unop.op) */
5717    } /* if (e->tag == Iex_Unop) */
5718 
5719    if (e->tag == Iex_Binop) {
5720       switch (e->Iex.Binop.op) {
5721 
5722       case Iop_64HLtoV128: {
5723          if (!mode64) {
5724             HReg     r3, r2, r1, r0, r_aligned16;
5725             PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
5726             HReg     dst = newVRegV(env);
5727             /* do this via the stack (easy, convenient, etc) */
5728             sub_from_sp( env, 32 );        // Move SP down
5729 
5730             // get a quadword aligned address within our stack space
5731             r_aligned16 = get_sp_aligned16( env );
5732             am_off0  = PPCAMode_IR( 0,  r_aligned16 );
5733             am_off4  = PPCAMode_IR( 4,  r_aligned16 );
5734             am_off8  = PPCAMode_IR( 8,  r_aligned16 );
5735             am_off12 = PPCAMode_IR( 12, r_aligned16 );
5736 
5737             /* Do the less significant 64 bits */
5738             iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2, IEndianess);
5739             addInstr(env, PPCInstr_Store( 4, am_off12, r0, mode64 ));
5740             addInstr(env, PPCInstr_Store( 4, am_off8,  r1, mode64 ));
5741             /* Do the more significant 64 bits */
5742             iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1, IEndianess);
5743             addInstr(env, PPCInstr_Store( 4, am_off4, r2, mode64 ));
5744             addInstr(env, PPCInstr_Store( 4, am_off0, r3, mode64 ));
5745 
5746             /* Fetch result back from stack. */
5747             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
5748 
5749             add_to_sp( env, 32 );          // Reset SP
5750             return dst;
5751          } else {
5752             HReg     rHi = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
5753             HReg     rLo = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
5754             HReg     dst = newVRegV(env);
5755             HReg     r_aligned16;
5756             PPCAMode *am_off0, *am_off8;
5757             /* do this via the stack (easy, convenient, etc) */
5758             sub_from_sp( env, 32 );        // Move SP down
5759 
5760             // get a quadword aligned address within our stack space
5761             r_aligned16 = get_sp_aligned16( env );
5762             am_off0  = PPCAMode_IR( 0,  r_aligned16 );
5763             am_off8  = PPCAMode_IR( 8,  r_aligned16 );
5764 
5765             /* Store 2*I64 to stack */
5766             if (IEndianess == Iend_LE) {
5767                addInstr(env, PPCInstr_Store( 8, am_off0, rLo, mode64 ));
5768                addInstr(env, PPCInstr_Store( 8, am_off8, rHi, mode64 ));
5769             } else {
5770                addInstr(env, PPCInstr_Store( 8, am_off0, rHi, mode64 ));
5771                addInstr(env, PPCInstr_Store( 8, am_off8, rLo, mode64 ));
5772             }
5773             /* Fetch result back from stack. */
5774             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
5775 
5776             add_to_sp( env, 32 );          // Reset SP
5777             return dst;
5778          }
5779       }
5780 
5781       case Iop_Max32Fx4:   fpop = Pavfp_MAXF;   goto do_32Fx4;
5782       case Iop_Min32Fx4:   fpop = Pavfp_MINF;   goto do_32Fx4;
5783       case Iop_CmpEQ32Fx4: fpop = Pavfp_CMPEQF; goto do_32Fx4;
5784       case Iop_CmpGT32Fx4: fpop = Pavfp_CMPGTF; goto do_32Fx4;
5785       case Iop_CmpGE32Fx4: fpop = Pavfp_CMPGEF; goto do_32Fx4;
5786       do_32Fx4:
5787       {
5788          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5789          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5790          HReg dst = newVRegV(env);
5791          addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
5792          return dst;
5793       }
5794 
5795       case Iop_CmpLE32Fx4: {
5796          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5797          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5798          HReg dst = newVRegV(env);
5799 
5800          /* stay consistent with native ppc compares:
5801             if a left/right lane holds a nan, return zeros for that lane
5802             so: le == NOT(gt OR isNan)
5803           */
5804          HReg isNanLR = newVRegV(env);
5805          HReg isNanL = isNan(env, argL, IEndianess);
5806          HReg isNanR = isNan(env, argR, IEndianess);
5807          addInstr(env, PPCInstr_AvBinary(Pav_OR, isNanLR,
5808                                          isNanL, isNanR));
5809 
5810          addInstr(env, PPCInstr_AvBin32Fx4(Pavfp_CMPGTF, dst,
5811                                            argL, argR));
5812          addInstr(env, PPCInstr_AvBinary(Pav_OR, dst, dst, isNanLR));
5813          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
5814          return dst;
5815       }
5816 
5817       case Iop_AndV128:    op = Pav_AND;      goto do_AvBin;
5818       case Iop_OrV128:     op = Pav_OR;       goto do_AvBin;
5819       case Iop_XorV128:    op = Pav_XOR;      goto do_AvBin;
5820       do_AvBin: {
5821          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5822          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5823          HReg dst  = newVRegV(env);
5824          addInstr(env, PPCInstr_AvBinary(op, dst, arg1, arg2));
5825          return dst;
5826       }
5827 
5828       case Iop_Shl8x16:    op = Pav_SHL;    goto do_AvBin8x16;
5829       case Iop_Shr8x16:    op = Pav_SHR;    goto do_AvBin8x16;
5830       case Iop_Sar8x16:    op = Pav_SAR;    goto do_AvBin8x16;
5831       case Iop_Rol8x16:    op = Pav_ROTL;   goto do_AvBin8x16;
5832       case Iop_InterleaveHI8x16: op = Pav_MRGHI;  goto do_AvBin8x16;
5833       case Iop_InterleaveLO8x16: op = Pav_MRGLO;  goto do_AvBin8x16;
5834       case Iop_Add8x16:    op = Pav_ADDU;   goto do_AvBin8x16;
5835       case Iop_QAdd8Ux16:  op = Pav_QADDU;  goto do_AvBin8x16;
5836       case Iop_QAdd8Sx16:  op = Pav_QADDS;  goto do_AvBin8x16;
5837       case Iop_Sub8x16:    op = Pav_SUBU;   goto do_AvBin8x16;
5838       case Iop_QSub8Ux16:  op = Pav_QSUBU;  goto do_AvBin8x16;
5839       case Iop_QSub8Sx16:  op = Pav_QSUBS;  goto do_AvBin8x16;
5840       case Iop_Avg8Ux16:   op = Pav_AVGU;   goto do_AvBin8x16;
5841       case Iop_Avg8Sx16:   op = Pav_AVGS;   goto do_AvBin8x16;
5842       case Iop_Max8Ux16:   op = Pav_MAXU;   goto do_AvBin8x16;
5843       case Iop_Max8Sx16:   op = Pav_MAXS;   goto do_AvBin8x16;
5844       case Iop_Min8Ux16:   op = Pav_MINU;   goto do_AvBin8x16;
5845       case Iop_Min8Sx16:   op = Pav_MINS;   goto do_AvBin8x16;
5846       case Iop_MullEven8Ux16: op = Pav_OMULU;  goto do_AvBin8x16;
5847       case Iop_MullEven8Sx16: op = Pav_OMULS;  goto do_AvBin8x16;
5848       case Iop_CmpEQ8x16:  op = Pav_CMPEQU; goto do_AvBin8x16;
5849       case Iop_CmpGT8Ux16: op = Pav_CMPGTU; goto do_AvBin8x16;
5850       case Iop_CmpGT8Sx16: op = Pav_CMPGTS; goto do_AvBin8x16;
5851       case Iop_PolynomialMulAdd8x16: op = Pav_POLYMULADD; goto do_AvBin8x16;
5852       do_AvBin8x16: {
5853          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5854          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5855          HReg dst  = newVRegV(env);
5856          addInstr(env, PPCInstr_AvBin8x16(op, dst, arg1, arg2));
5857          return dst;
5858       }
5859 
5860       case Iop_Shl16x8:    op = Pav_SHL;    goto do_AvBin16x8;
5861       case Iop_Shr16x8:    op = Pav_SHR;    goto do_AvBin16x8;
5862       case Iop_Sar16x8:    op = Pav_SAR;    goto do_AvBin16x8;
5863       case Iop_Rol16x8:    op = Pav_ROTL;   goto do_AvBin16x8;
5864       case Iop_NarrowBin16to8x16:    op = Pav_PACKUU;  goto do_AvBin16x8;
5865       case Iop_QNarrowBin16Uto8Ux16: op = Pav_QPACKUU; goto do_AvBin16x8;
5866       case Iop_QNarrowBin16Sto8Sx16: op = Pav_QPACKSS; goto do_AvBin16x8;
5867       case Iop_InterleaveHI16x8:  op = Pav_MRGHI;  goto do_AvBin16x8;
5868       case Iop_InterleaveLO16x8:  op = Pav_MRGLO;  goto do_AvBin16x8;
5869       case Iop_Add16x8:    op = Pav_ADDU;   goto do_AvBin16x8;
5870       case Iop_QAdd16Ux8:  op = Pav_QADDU;  goto do_AvBin16x8;
5871       case Iop_QAdd16Sx8:  op = Pav_QADDS;  goto do_AvBin16x8;
5872       case Iop_Sub16x8:    op = Pav_SUBU;   goto do_AvBin16x8;
5873       case Iop_QSub16Ux8:  op = Pav_QSUBU;  goto do_AvBin16x8;
5874       case Iop_QSub16Sx8:  op = Pav_QSUBS;  goto do_AvBin16x8;
5875       case Iop_Avg16Ux8:   op = Pav_AVGU;   goto do_AvBin16x8;
5876       case Iop_Avg16Sx8:   op = Pav_AVGS;   goto do_AvBin16x8;
5877       case Iop_Max16Ux8:   op = Pav_MAXU;   goto do_AvBin16x8;
5878       case Iop_Max16Sx8:   op = Pav_MAXS;   goto do_AvBin16x8;
5879       case Iop_Min16Ux8:   op = Pav_MINU;   goto do_AvBin16x8;
5880       case Iop_Min16Sx8:   op = Pav_MINS;   goto do_AvBin16x8;
5881       case Iop_MullEven16Ux8: op = Pav_OMULU;  goto do_AvBin16x8;
5882       case Iop_MullEven16Sx8: op = Pav_OMULS;  goto do_AvBin16x8;
5883       case Iop_CmpEQ16x8:  op = Pav_CMPEQU; goto do_AvBin16x8;
5884       case Iop_CmpGT16Ux8: op = Pav_CMPGTU; goto do_AvBin16x8;
5885       case Iop_CmpGT16Sx8: op = Pav_CMPGTS; goto do_AvBin16x8;
5886       case Iop_PolynomialMulAdd16x8: op = Pav_POLYMULADD; goto do_AvBin16x8;
5887       do_AvBin16x8: {
5888          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5889          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5890          HReg dst  = newVRegV(env);
5891          addInstr(env, PPCInstr_AvBin16x8(op, dst, arg1, arg2));
5892          return dst;
5893       }
5894 
5895       case Iop_Shl32x4:    op = Pav_SHL;    goto do_AvBin32x4;
5896       case Iop_Shr32x4:    op = Pav_SHR;    goto do_AvBin32x4;
5897       case Iop_Sar32x4:    op = Pav_SAR;    goto do_AvBin32x4;
5898       case Iop_Rol32x4:    op = Pav_ROTL;   goto do_AvBin32x4;
5899       case Iop_NarrowBin32to16x8:    op = Pav_PACKUU;  goto do_AvBin32x4;
5900       case Iop_QNarrowBin32Uto16Ux8: op = Pav_QPACKUU; goto do_AvBin32x4;
5901       case Iop_QNarrowBin32Sto16Sx8: op = Pav_QPACKSS; goto do_AvBin32x4;
5902       case Iop_InterleaveHI32x4:  op = Pav_MRGHI;  goto do_AvBin32x4;
5903       case Iop_InterleaveLO32x4:  op = Pav_MRGLO;  goto do_AvBin32x4;
5904       case Iop_Add32x4:    op = Pav_ADDU;   goto do_AvBin32x4;
5905       case Iop_QAdd32Ux4:  op = Pav_QADDU;  goto do_AvBin32x4;
5906       case Iop_QAdd32Sx4:  op = Pav_QADDS;  goto do_AvBin32x4;
5907       case Iop_Sub32x4:    op = Pav_SUBU;   goto do_AvBin32x4;
5908       case Iop_QSub32Ux4:  op = Pav_QSUBU;  goto do_AvBin32x4;
5909       case Iop_QSub32Sx4:  op = Pav_QSUBS;  goto do_AvBin32x4;
5910       case Iop_Avg32Ux4:   op = Pav_AVGU;   goto do_AvBin32x4;
5911       case Iop_Avg32Sx4:   op = Pav_AVGS;   goto do_AvBin32x4;
5912       case Iop_Max32Ux4:   op = Pav_MAXU;   goto do_AvBin32x4;
5913       case Iop_Max32Sx4:   op = Pav_MAXS;   goto do_AvBin32x4;
5914       case Iop_Min32Ux4:   op = Pav_MINU;   goto do_AvBin32x4;
5915       case Iop_Min32Sx4:   op = Pav_MINS;   goto do_AvBin32x4;
5916       case Iop_Mul32x4:    op = Pav_MULU;   goto do_AvBin32x4;
5917       case Iop_MullEven32Ux4: op = Pav_OMULU;  goto do_AvBin32x4;
5918       case Iop_MullEven32Sx4: op = Pav_OMULS;  goto do_AvBin32x4;
5919       case Iop_CmpEQ32x4:  op = Pav_CMPEQU; goto do_AvBin32x4;
5920       case Iop_CmpGT32Ux4: op = Pav_CMPGTU; goto do_AvBin32x4;
5921       case Iop_CmpGT32Sx4: op = Pav_CMPGTS; goto do_AvBin32x4;
5922       case Iop_CatOddLanes32x4:  op = Pav_CATODD;  goto do_AvBin32x4;
5923       case Iop_CatEvenLanes32x4: op = Pav_CATEVEN; goto do_AvBin32x4;
5924       case Iop_PolynomialMulAdd32x4: op = Pav_POLYMULADD; goto do_AvBin32x4;
5925       do_AvBin32x4: {
5926          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5927          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5928          HReg dst  = newVRegV(env);
5929          addInstr(env, PPCInstr_AvBin32x4(op, dst, arg1, arg2));
5930          return dst;
5931       }
5932 
5933       case Iop_Shl64x2:    op = Pav_SHL;    goto do_AvBin64x2;
5934       case Iop_Shr64x2:    op = Pav_SHR;    goto do_AvBin64x2;
5935       case Iop_Sar64x2:    op = Pav_SAR;    goto do_AvBin64x2;
5936       case Iop_Rol64x2:    op = Pav_ROTL;   goto do_AvBin64x2;
5937       case Iop_NarrowBin64to32x4:    op = Pav_PACKUU;  goto do_AvBin64x2;
5938       case Iop_QNarrowBin64Sto32Sx4: op = Pav_QPACKSS; goto do_AvBin64x2;
5939       case Iop_QNarrowBin64Uto32Ux4: op = Pav_QPACKUU; goto do_AvBin64x2;
5940       case Iop_InterleaveHI64x2:  op = Pav_MRGHI;  goto do_AvBin64x2;
5941       case Iop_InterleaveLO64x2:  op = Pav_MRGLO;  goto do_AvBin64x2;
5942       case Iop_Add64x2:    op = Pav_ADDU;   goto do_AvBin64x2;
5943       case Iop_Sub64x2:    op = Pav_SUBU;   goto do_AvBin64x2;
5944       case Iop_Max64Ux2:   op = Pav_MAXU;   goto do_AvBin64x2;
5945       case Iop_Max64Sx2:   op = Pav_MAXS;   goto do_AvBin64x2;
5946       case Iop_Min64Ux2:   op = Pav_MINU;   goto do_AvBin64x2;
5947       case Iop_Min64Sx2:   op = Pav_MINS;   goto do_AvBin64x2;
5948       case Iop_CmpEQ64x2:  op = Pav_CMPEQU; goto do_AvBin64x2;
5949       case Iop_CmpGT64Ux2: op = Pav_CMPGTU; goto do_AvBin64x2;
5950       case Iop_CmpGT64Sx2: op = Pav_CMPGTS; goto do_AvBin64x2;
5951       case Iop_PolynomialMulAdd64x2: op = Pav_POLYMULADD; goto do_AvBin64x2;
5952       do_AvBin64x2: {
5953          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5954          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
5955          HReg dst  = newVRegV(env);
5956          addInstr(env, PPCInstr_AvBin64x2(op, dst, arg1, arg2));
5957          return dst;
5958       }
5959 
5960       case Iop_ShlN8x16: op = Pav_SHL; goto do_AvShift8x16;
5961       case Iop_SarN8x16: op = Pav_SAR; goto do_AvShift8x16;
5962       do_AvShift8x16: {
5963          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5964          HReg dst    = newVRegV(env);
5965          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
5966          addInstr(env, PPCInstr_AvBin8x16(op, dst, r_src, v_shft));
5967          return dst;
5968       }
5969 
5970       case Iop_ShlN16x8: op = Pav_SHL; goto do_AvShift16x8;
5971       case Iop_ShrN16x8: op = Pav_SHR; goto do_AvShift16x8;
5972       case Iop_SarN16x8: op = Pav_SAR; goto do_AvShift16x8;
5973       do_AvShift16x8: {
5974          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5975          HReg dst    = newVRegV(env);
5976          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
5977          addInstr(env, PPCInstr_AvBin16x8(op, dst, r_src, v_shft));
5978          return dst;
5979       }
5980 
5981       case Iop_ShlN32x4: op = Pav_SHL; goto do_AvShift32x4;
5982       case Iop_ShrN32x4: op = Pav_SHR; goto do_AvShift32x4;
5983       case Iop_SarN32x4: op = Pav_SAR; goto do_AvShift32x4;
5984       do_AvShift32x4: {
5985          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5986          HReg dst    = newVRegV(env);
5987          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
5988          addInstr(env, PPCInstr_AvBin32x4(op, dst, r_src, v_shft));
5989          return dst;
5990       }
5991 
5992       case Iop_ShlN64x2: op = Pav_SHL; goto do_AvShift64x2;
5993       case Iop_ShrN64x2: op = Pav_SHR; goto do_AvShift64x2;
5994       case Iop_SarN64x2: op = Pav_SAR; goto do_AvShift64x2;
5995       do_AvShift64x2: {
5996          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
5997          HReg dst    = newVRegV(env);
5998          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
5999          addInstr(env, PPCInstr_AvBin64x2(op, dst, r_src, v_shft));
6000          return dst;
6001       }
6002 
6003       case Iop_ShrV128: op = Pav_SHR; goto do_AvShiftV128;
6004       case Iop_ShlV128: op = Pav_SHL; goto do_AvShiftV128;
6005       do_AvShiftV128: {
6006          HReg dst    = newVRegV(env);
6007          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6008          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
6009          /* Note: shift value gets masked by 127 */
6010          addInstr(env, PPCInstr_AvBinary(op, dst, r_src, v_shft));
6011          return dst;
6012       }
6013 
6014       case Iop_Perm8x16: {
6015          HReg dst   = newVRegV(env);
6016          HReg v_src = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6017          HReg v_ctl = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6018          addInstr(env, PPCInstr_AvPerm(dst, v_src, v_src, v_ctl));
6019          return dst;
6020       }
6021 
6022       case Iop_CipherV128:  op = Pav_CIPHERV128;   goto do_AvCipherV128;
6023       case Iop_CipherLV128: op = Pav_CIPHERLV128;  goto do_AvCipherV128;
6024       case Iop_NCipherV128: op = Pav_NCIPHERV128;  goto do_AvCipherV128;
6025       case Iop_NCipherLV128:op = Pav_NCIPHERLV128; goto do_AvCipherV128;
6026       do_AvCipherV128: {
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_AvCipherV128Binary(op, dst, arg1, arg2));
6031          return dst;
6032       }
6033 
6034       case Iop_SHA256:op = Pav_SHA256; goto do_AvHashV128;
6035       case Iop_SHA512:op = Pav_SHA512; goto do_AvHashV128;
6036       do_AvHashV128: {
6037          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6038          HReg dst  = newVRegV(env);
6039          PPCRI* s_field = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
6040          addInstr(env, PPCInstr_AvHashV128Binary(op, dst, arg1, s_field));
6041          return dst;
6042       }
6043 
6044       /* BCD Iops */
6045       case Iop_I128StoBCD128:
6046          {
6047             HReg dst = newVRegV(env);
6048             HReg arg = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6049             PPCRI* ps = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
6050 
6051             addInstr(env, PPCInstr_AvBinaryInt( Pav_I128StoBCD128, dst, arg,
6052                                                 ps ) );
6053             return dst;
6054          }
6055 
6056       case Iop_MulI128by10E:       op = Pav_MulI128by10E;      goto do_MulI128E;
6057       case Iop_MulI128by10ECarry:  op = Pav_MulI128by10ECarry; goto do_MulI128E;
6058       do_MulI128E: {
6059             HReg dst  = newVRegV(env);
6060             HReg argL = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6061             HReg argR = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6062             addInstr(env, PPCInstr_AvBinary(op, dst, argL, argR));
6063             return dst;
6064          }
6065 
6066       case Iop_BCDAdd:op = Pav_BCDAdd; goto do_AvBCDV128;
6067       case Iop_BCDSub:op = Pav_BCDSub; goto do_AvBCDV128;
6068       do_AvBCDV128: {
6069          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
6070          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
6071          HReg dst  = newVRegV(env);
6072          addInstr(env, PPCInstr_AvBCDV128Binary(op, dst, arg1, arg2));
6073          return dst;
6074       }
6075 
6076       default:
6077          break;
6078       } /* switch (e->Iex.Binop.op) */
6079    } /* if (e->tag == Iex_Binop) */
6080 
6081    if (e->tag == Iex_Triop) {
6082       IRTriop *triop = e->Iex.Triop.details;
6083       switch (triop->op) {
6084       case Iop_Add32Fx4: fpop = Pavfp_ADDF; goto do_32Fx4_with_rm;
6085       case Iop_Sub32Fx4: fpop = Pavfp_SUBF; goto do_32Fx4_with_rm;
6086       case Iop_Mul32Fx4: fpop = Pavfp_MULF; goto do_32Fx4_with_rm;
6087       do_32Fx4_with_rm:
6088       {
6089          HReg argL = iselVecExpr(env, triop->arg2, IEndianess);
6090          HReg argR = iselVecExpr(env, triop->arg3, IEndianess);
6091          HReg dst  = newVRegV(env);
6092          /* FIXME: this is bogus, in the sense that Altivec ignores
6093             FPSCR.RM, at least for some FP operations.  So setting the
6094             RM is pointless.  This is only really correct in the case
6095             where the RM is known, at JIT time, to be Irrm_NEAREST,
6096             since -- at least for Altivec FP add/sub/mul -- the
6097             emitted insn is hardwired to round to nearest. */
6098          set_FPU_rounding_mode(env, triop->arg1, IEndianess);
6099          addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
6100          return dst;
6101       }
6102 
6103       default:
6104          break;
6105       } /* switch (e->Iex.Triop.op) */
6106    } /* if (e->tag == Iex_Trinop) */
6107 
6108 
6109    if (e->tag == Iex_Const ) {
6110       vassert(e->Iex.Const.con->tag == Ico_V128);
6111       if (e->Iex.Const.con->Ico.V128 == 0x0000) {
6112          return generate_zeroes_V128(env);
6113       }
6114       else if (e->Iex.Const.con->Ico.V128 == 0xffff) {
6115          return generate_ones_V128(env);
6116       }
6117    }
6118 
6119    vex_printf("iselVecExpr(ppc) (subarch = %s): can't reduce\n",
6120               LibVEX_ppVexHwCaps(mode64 ? VexArchPPC64 : VexArchPPC32,
6121                                  env->hwcaps));
6122    ppIRExpr(e);
6123    vpanic("iselVecExpr_wrk(ppc)");
6124 }
6125 
6126 
6127 /*---------------------------------------------------------*/
6128 /*--- ISEL: Statements                                  ---*/
6129 /*---------------------------------------------------------*/
6130 
iselStmt(ISelEnv * env,IRStmt * stmt,IREndness IEndianess)6131 static void iselStmt ( ISelEnv* env, IRStmt* stmt, IREndness IEndianess )
6132 {
6133    Bool mode64 = env->mode64;
6134    if (vex_traceflags & VEX_TRACE_VCODE) {
6135       vex_printf("\n -- ");
6136       ppIRStmt(stmt);
6137       vex_printf("\n");
6138    }
6139 
6140    switch (stmt->tag) {
6141 
6142    /* --------- STORE --------- */
6143    case Ist_Store: {
6144       IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
6145       IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
6146       IREndness end   = stmt->Ist.Store.end;
6147 
6148       if (end != IEndianess)
6149          goto stmt_fail;
6150       if (!mode64 && (tya != Ity_I32))
6151          goto stmt_fail;
6152       if (mode64 && (tya != Ity_I64))
6153          goto stmt_fail;
6154 
6155       if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
6156           (mode64 && (tyd == Ity_I64))) {
6157          PPCAMode* am_addr
6158             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6159                                  IEndianess);
6160          HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data, IEndianess);
6161          addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(tyd)),
6162                                        am_addr, r_src, mode64 ));
6163          return;
6164       }
6165       if (tyd == Ity_F64) {
6166          PPCAMode* am_addr
6167             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6168                                  IEndianess);
6169          HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data, IEndianess);
6170          addInstr(env,
6171                   PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
6172          return;
6173       }
6174       if (tyd == Ity_F32) {
6175          PPCAMode* am_addr
6176             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6177                                  IEndianess);
6178          HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data, IEndianess);
6179          addInstr(env,
6180                   PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
6181          return;
6182       }
6183       if (tyd == Ity_D64) {
6184          PPCAMode* am_addr
6185             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6186                                  IEndianess);
6187          HReg fr_src = iselDfp64Expr(env, stmt->Ist.Store.data, IEndianess);
6188          addInstr(env,
6189                   PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
6190          return;
6191       }
6192       if (tyd == Ity_D32) {
6193          PPCAMode* am_addr
6194             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6195                                  IEndianess);
6196          HReg fr_src = iselDfp32Expr(env, stmt->Ist.Store.data, IEndianess);
6197          addInstr(env,
6198                   PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
6199          return;
6200       }
6201       if (tyd == Ity_V128) {
6202          PPCAMode* am_addr
6203             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
6204                                  IEndianess);
6205          HReg v_src = iselVecExpr(env, stmt->Ist.Store.data, IEndianess);
6206          addInstr(env,
6207                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
6208          return;
6209       }
6210       if (tyd == Ity_I64 && !mode64) {
6211          /* Just calculate the address in the register.  Life is too
6212             short to arse around trying and possibly failing to adjust
6213             the offset in a 'reg+offset' style amode. */
6214          HReg rHi32, rLo32;
6215          HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr, IEndianess);
6216          iselInt64Expr( &rHi32, &rLo32, env, stmt->Ist.Store.data,
6217                         IEndianess );
6218          addInstr(env, PPCInstr_Store( 4/*byte-store*/,
6219                                        PPCAMode_IR( 0, r_addr ),
6220                                        rHi32,
6221                                        False/*32-bit insn please*/) );
6222          addInstr(env, PPCInstr_Store( 4/*byte-store*/,
6223                                        PPCAMode_IR( 4, r_addr ),
6224                                        rLo32,
6225                                        False/*32-bit insn please*/) );
6226          return;
6227       }
6228       break;
6229    }
6230 
6231    /* --------- PUT --------- */
6232    case Ist_Put: {
6233       IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
6234       if (ty == Ity_I8  || ty == Ity_I16 ||
6235           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
6236          HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data, IEndianess);
6237          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
6238                                           GuestStatePtr(mode64) );
6239          addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(ty)),
6240                                        am_addr, r_src, mode64 ));
6241          return;
6242       }
6243       if (!mode64 && ty == Ity_I64) {
6244          HReg rHi, rLo;
6245          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
6246                                            GuestStatePtr(mode64) );
6247          PPCAMode* am_addr4 = advance4(env, am_addr);
6248          iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Put.data, IEndianess);
6249          addInstr(env, PPCInstr_Store( 4, am_addr,  rHi, mode64 ));
6250          addInstr(env, PPCInstr_Store( 4, am_addr4, rLo, mode64 ));
6251          return;
6252       }
6253       if (ty == Ity_I128) {
6254          HReg rHi, rLo;
6255          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
6256                                            GuestStatePtr(mode64) );
6257          PPCAMode* am_addr4 = advance4(env, am_addr);
6258 
6259          iselInt128Expr(&rHi,&rLo, env, stmt->Ist.Put.data, IEndianess);
6260          addInstr(env, PPCInstr_Store( 4, am_addr,  rHi, mode64 ));
6261          addInstr(env, PPCInstr_Store( 4, am_addr4, rLo, mode64 ));
6262          return;
6263       }
6264       if (ty == Ity_F128) {
6265          /* Guest state vectors are 16byte aligned,
6266             so don't need to worry here */
6267          HReg v_src = iselFp128Expr(env, stmt->Ist.Put.data, IEndianess);
6268 
6269          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
6270                                            GuestStatePtr(mode64) );
6271          addInstr(env,
6272                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
6273          return;
6274       }
6275       if (ty == Ity_V128) {
6276          /* Guest state vectors are 16byte aligned,
6277             so don't need to worry here */
6278          HReg v_src = iselVecExpr(env, stmt->Ist.Put.data, IEndianess);
6279          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
6280                                            GuestStatePtr(mode64) );
6281          addInstr(env,
6282                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
6283          return;
6284       }
6285       if (ty == Ity_F64) {
6286          HReg fr_src = iselDblExpr(env, stmt->Ist.Put.data, IEndianess);
6287          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
6288                                           GuestStatePtr(mode64) );
6289          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
6290                                         fr_src, am_addr ));
6291          return;
6292       }
6293       if (ty == Ity_D32) {
6294          /* The 32-bit value is stored in a 64-bit register */
6295          HReg fr_src = iselDfp32Expr( env, stmt->Ist.Put.data, IEndianess );
6296          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
6297                                           GuestStatePtr(mode64) );
6298          addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8,
6299                                          fr_src, am_addr ) );
6300          return;
6301       }
6302       if (ty == Ity_D64) {
6303          HReg fr_src = iselDfp64Expr( env, stmt->Ist.Put.data, IEndianess );
6304          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
6305                                           GuestStatePtr(mode64) );
6306          addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8, fr_src, am_addr ) );
6307          return;
6308       }
6309       break;
6310    }
6311 
6312    /* --------- Indexed PUT --------- */
6313    case Ist_PutI: {
6314       IRPutI *puti = stmt->Ist.PutI.details;
6315 
6316       PPCAMode* dst_am
6317          = genGuestArrayOffset(
6318               env, puti->descr,
6319               puti->ix, puti->bias,
6320               IEndianess );
6321       IRType ty = typeOfIRExpr(env->type_env, puti->data);
6322       if (mode64 && ty == Ity_I64) {
6323          HReg r_src = iselWordExpr_R(env, puti->data, IEndianess);
6324          addInstr(env, PPCInstr_Store( toUChar(8),
6325                                        dst_am, r_src, mode64 ));
6326          return;
6327       }
6328       if ((!mode64) && ty == Ity_I32) {
6329          HReg r_src = iselWordExpr_R(env, puti->data, IEndianess);
6330          addInstr(env, PPCInstr_Store( toUChar(4),
6331                                        dst_am, r_src, mode64 ));
6332          return;
6333       }
6334       break;
6335    }
6336 
6337    /* --------- TMP --------- */
6338    case Ist_WrTmp: {
6339       IRTemp tmp = stmt->Ist.WrTmp.tmp;
6340       IRType ty = typeOfIRTemp(env->type_env, tmp);
6341       if (ty == Ity_I8  || ty == Ity_I16 ||
6342           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
6343          HReg r_dst = lookupIRTemp(env, tmp);
6344          HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data, IEndianess);
6345          addInstr(env, mk_iMOVds_RR( r_dst, r_src ));
6346          return;
6347       }
6348       if (!mode64 && ty == Ity_I64) {
6349          HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
6350 
6351          iselInt64Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data,
6352                        IEndianess);
6353          lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
6354          addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
6355          addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
6356          return;
6357       }
6358       if (mode64 && ty == Ity_I128) {
6359          HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
6360          iselInt128Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data,
6361                         IEndianess);
6362          lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
6363          addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
6364          addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
6365          return;
6366       }
6367       if (!mode64 && ty == Ity_I128) {
6368          HReg r_srcHi, r_srcMedHi, r_srcMedLo, r_srcLo;
6369          HReg r_dstHi, r_dstMedHi, r_dstMedLo, r_dstLo;
6370 
6371          iselInt128Expr_to_32x4(&r_srcHi, &r_srcMedHi,
6372                                 &r_srcMedLo, &r_srcLo,
6373                                 env, stmt->Ist.WrTmp.data, IEndianess);
6374 
6375          lookupIRTempQuad( &r_dstHi, &r_dstMedHi, &r_dstMedLo,
6376                            &r_dstLo, env, tmp);
6377 
6378          addInstr(env, mk_iMOVds_RR(r_dstHi,    r_srcHi) );
6379          addInstr(env, mk_iMOVds_RR(r_dstMedHi, r_srcMedHi) );
6380          addInstr(env, mk_iMOVds_RR(r_dstMedLo, r_srcMedLo) );
6381          addInstr(env, mk_iMOVds_RR(r_dstLo,    r_srcLo) );
6382          return;
6383       }
6384       if (ty == Ity_I1) {
6385          PPCCondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data,
6386                                          IEndianess);
6387          HReg r_dst = lookupIRTemp(env, tmp);
6388          addInstr(env, PPCInstr_Set(cond, r_dst));
6389          return;
6390       }
6391       if (ty == Ity_F64) {
6392          HReg fr_dst = lookupIRTemp(env, tmp);
6393          HReg fr_src = iselDblExpr(env, stmt->Ist.WrTmp.data, IEndianess);
6394          addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
6395          return;
6396       }
6397       if (ty == Ity_F32) {
6398          HReg fr_dst = lookupIRTemp(env, tmp);
6399          HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data, IEndianess);
6400          addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
6401          return;
6402       }
6403       if (ty == Ity_D32) {
6404          HReg fr_dst = lookupIRTemp(env, tmp);
6405          HReg fr_src = iselDfp32Expr(env, stmt->Ist.WrTmp.data, IEndianess);
6406          addInstr(env, PPCInstr_Dfp64Unary(Pfp_MOV, fr_dst, fr_src));
6407          return;
6408       }
6409       if (ty == Ity_F128) {
6410          HReg v_dst = lookupIRTemp(env, tmp);
6411          HReg v_src = iselFp128Expr(env, stmt->Ist.WrTmp.data, IEndianess);
6412          addInstr(env, PPCInstr_AvUnary(Pav_MOV, v_dst, v_src));
6413          return;
6414       }
6415       if (ty == Ity_V128) {
6416          HReg v_dst = lookupIRTemp(env, tmp);
6417          HReg v_src = iselVecExpr(env, stmt->Ist.WrTmp.data, IEndianess);
6418          addInstr(env, PPCInstr_AvUnary(Pav_MOV, v_dst, v_src));
6419          return;
6420       }
6421       if (ty == Ity_D64) {
6422          HReg fr_dst = lookupIRTemp( env, tmp );
6423          HReg fr_src = iselDfp64Expr( env, stmt->Ist.WrTmp.data, IEndianess );
6424          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dst, fr_src ) );
6425          return;
6426       }
6427       if (ty == Ity_D128) {
6428          HReg fr_srcHi, fr_srcLo, fr_dstHi, fr_dstLo;
6429 	 //         lookupDfp128IRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
6430          lookupIRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
6431          iselDfp128Expr( &fr_srcHi, &fr_srcLo, env, stmt->Ist.WrTmp.data,
6432                          IEndianess );
6433          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstHi, fr_srcHi ) );
6434          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstLo, fr_srcLo ) );
6435          return;
6436       }
6437       break;
6438    }
6439 
6440    /* --------- Load Linked or Store Conditional --------- */
6441    case Ist_LLSC: {
6442       IRTemp res    = stmt->Ist.LLSC.result;
6443       IRType tyRes  = typeOfIRTemp(env->type_env, res);
6444       IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
6445 
6446       if (stmt->Ist.LLSC.end != IEndianess)
6447          goto stmt_fail;
6448       if (!mode64 && (tyAddr != Ity_I32))
6449          goto stmt_fail;
6450       if (mode64 && (tyAddr != Ity_I64))
6451          goto stmt_fail;
6452 
6453       if (stmt->Ist.LLSC.storedata == NULL) {
6454          /* LL */
6455          HReg r_addr = iselWordExpr_R( env, stmt->Ist.LLSC.addr, IEndianess );
6456          HReg r_dst  = lookupIRTemp(env, res);
6457          if (tyRes == Ity_I8) {
6458             addInstr(env, PPCInstr_LoadL( 1, r_dst, r_addr, mode64 ));
6459             return;
6460          }
6461          if (tyRes == Ity_I16) {
6462             addInstr(env, PPCInstr_LoadL( 2, r_dst, r_addr, mode64 ));
6463             return;
6464          }
6465          if (tyRes == Ity_I32) {
6466             addInstr(env, PPCInstr_LoadL( 4, r_dst, r_addr, mode64 ));
6467             return;
6468          }
6469          if (tyRes == Ity_I64 && mode64) {
6470             addInstr(env, PPCInstr_LoadL( 8, r_dst, r_addr, mode64 ));
6471             return;
6472          }
6473          /* fallthru */;
6474       } else {
6475          /* SC */
6476          HReg   r_res  = lookupIRTemp(env, res); /* :: Ity_I1 */
6477          HReg   r_a    = iselWordExpr_R(env, stmt->Ist.LLSC.addr, IEndianess);
6478          HReg   r_src  = iselWordExpr_R(env, stmt->Ist.LLSC.storedata,
6479                                         IEndianess);
6480          HReg   r_tmp  = newVRegI(env);
6481          IRType tyData = typeOfIRExpr(env->type_env,
6482                                       stmt->Ist.LLSC.storedata);
6483          vassert(tyRes == Ity_I1);
6484          if (tyData == Ity_I8 || tyData == Ity_I16 || tyData == Ity_I32 ||
6485             (tyData == Ity_I64 && mode64)) {
6486             int size = 0;
6487 
6488             if (tyData == Ity_I64)
6489                size = 8;
6490             else if (tyData == Ity_I32)
6491                size = 4;
6492             else if (tyData == Ity_I16)
6493                size = 2;
6494             else if (tyData == Ity_I8)
6495                size = 1;
6496 
6497             addInstr(env, PPCInstr_StoreC( size,
6498                                            r_a, r_src, mode64 ));
6499             addInstr(env, PPCInstr_MfCR( r_tmp ));
6500             addInstr(env, PPCInstr_Shft(
6501                              Pshft_SHR,
6502                              env->mode64 ? False : True
6503                                 /*F:64-bit, T:32-bit shift*/,
6504                              r_tmp, r_tmp,
6505                              PPCRH_Imm(False/*unsigned*/, 29)));
6506             /* Probably unnecessary, since the IR dest type is Ity_I1,
6507                and so we are entitled to leave whatever junk we like
6508                drifting round in the upper 31 or 63 bits of r_res.
6509                However, for the sake of conservativeness .. */
6510             addInstr(env, PPCInstr_Alu(
6511                              Palu_AND,
6512                              r_res, r_tmp,
6513                              PPCRH_Imm(False/*signed*/, 1)));
6514             return;
6515          }
6516          /* fallthru */
6517       }
6518       goto stmt_fail;
6519       /*NOTREACHED*/
6520    }
6521 
6522    /* --------- Call to DIRTY helper --------- */
6523    case Ist_Dirty: {
6524       IRDirty* d = stmt->Ist.Dirty.details;
6525 
6526       /* Figure out the return type, if any. */
6527       IRType retty = Ity_INVALID;
6528       if (d->tmp != IRTemp_INVALID)
6529          retty = typeOfIRTemp(env->type_env, d->tmp);
6530 
6531       /* Throw out any return types we don't know about.  The set of
6532          acceptable return types is the same in both 32- and 64-bit
6533          mode, so we don't need to inspect mode64 to make a
6534          decision. */
6535       Bool retty_ok = False;
6536       switch (retty) {
6537          case Ity_INVALID: /* function doesn't return anything */
6538          case Ity_V128:
6539          case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
6540             retty_ok = True; break;
6541          default:
6542             break;
6543       }
6544       if (!retty_ok)
6545          break; /* will go to stmt_fail: */
6546 
6547       /* Marshal args, do the call, clear stack, set the return value
6548          to 0x555..555 if this is a conditional call that returns a
6549          value and the call is skipped. */
6550       UInt   addToSp = 0;
6551       RetLoc rloc    = mk_RetLoc_INVALID();
6552       doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args,
6553                     IEndianess );
6554       vassert(is_sane_RetLoc(rloc));
6555 
6556       /* Now figure out what to do with the returned value, if any. */
6557       switch (retty) {
6558          case Ity_INVALID: {
6559             /* No return value.  Nothing to do. */
6560             vassert(d->tmp == IRTemp_INVALID);
6561             vassert(rloc.pri == RLPri_None);
6562             vassert(addToSp == 0);
6563             return;
6564          }
6565          case Ity_I32: case Ity_I16: case Ity_I8: {
6566             /* The returned value is in %r3.  Park it in the register
6567                associated with tmp. */
6568             HReg r_dst = lookupIRTemp(env, d->tmp);
6569             addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
6570             vassert(rloc.pri == RLPri_Int);
6571             vassert(addToSp == 0);
6572             return;
6573          }
6574          case Ity_I64:
6575             if (mode64) {
6576                /* The returned value is in %r3.  Park it in the register
6577                   associated with tmp. */
6578                HReg r_dst = lookupIRTemp(env, d->tmp);
6579                addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
6580                vassert(rloc.pri == RLPri_Int);
6581                vassert(addToSp == 0);
6582             } else {
6583                /* The returned value is in %r3:%r4.  Park it in the
6584                   register-pair associated with tmp. */
6585                HReg r_dstHi = INVALID_HREG;
6586                HReg r_dstLo = INVALID_HREG;
6587                lookupIRTempPair( &r_dstHi, &r_dstLo, env, d->tmp);
6588                addInstr(env, mk_iMOVds_RR(r_dstHi, hregPPC_GPR3(mode64)));
6589                addInstr(env, mk_iMOVds_RR(r_dstLo, hregPPC_GPR4(mode64)));
6590                vassert(rloc.pri == RLPri_2Int);
6591                vassert(addToSp == 0);
6592             }
6593             return;
6594          case Ity_V128: {
6595             /* The returned value is on the stack, and *retloc tells
6596                us where.  Fish it off the stack and then move the
6597                stack pointer upwards to clear it, as directed by
6598                doHelperCall. */
6599             vassert(rloc.pri == RLPri_V128SpRel);
6600             vassert(addToSp >= 16);
6601             HReg      dst = lookupIRTemp(env, d->tmp);
6602             PPCAMode* am  = PPCAMode_IR(rloc.spOff, StackFramePtr(mode64));
6603             addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, dst, am ));
6604             add_to_sp(env, addToSp);
6605             return;
6606          }
6607          default:
6608             /*NOTREACHED*/
6609             vassert(0);
6610       }
6611    }
6612 
6613    /* --------- MEM FENCE --------- */
6614    case Ist_MBE:
6615       switch (stmt->Ist.MBE.event) {
6616          case Imbe_Fence:
6617             addInstr(env, PPCInstr_MFence());
6618             return;
6619          default:
6620             break;
6621       }
6622       break;
6623 
6624    /* --------- INSTR MARK --------- */
6625    /* Doesn't generate any executable code ... */
6626    case Ist_IMark:
6627        return;
6628 
6629    /* --------- ABI HINT --------- */
6630    /* These have no meaning (denotation in the IR) and so we ignore
6631       them ... if any actually made it this far. */
6632    case Ist_AbiHint:
6633        return;
6634 
6635    /* --------- NO-OP --------- */
6636    /* Fairly self-explanatory, wouldn't you say? */
6637    case Ist_NoOp:
6638        return;
6639 
6640    /* --------- EXIT --------- */
6641    case Ist_Exit: {
6642       IRConst* dst = stmt->Ist.Exit.dst;
6643       if (!mode64 && dst->tag != Ico_U32)
6644          vpanic("iselStmt(ppc): Ist_Exit: dst is not a 32-bit value");
6645       if (mode64 && dst->tag != Ico_U64)
6646          vpanic("iselStmt(ppc64): Ist_Exit: dst is not a 64-bit value");
6647 
6648       PPCCondCode cc    = iselCondCode(env, stmt->Ist.Exit.guard, IEndianess);
6649       PPCAMode*   amCIA = PPCAMode_IR(stmt->Ist.Exit.offsIP,
6650                                       hregPPC_GPR31(mode64));
6651 
6652       /* Case: boring transfer to known address */
6653       if (stmt->Ist.Exit.jk == Ijk_Boring
6654           || stmt->Ist.Exit.jk == Ijk_Call
6655           /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
6656          if (env->chainingAllowed) {
6657             /* .. almost always true .. */
6658             /* Skip the event check at the dst if this is a forwards
6659                edge. */
6660             Bool toFastEP
6661                = mode64
6662                ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
6663                : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
6664             if (0) vex_printf("%s", toFastEP ? "Y" : ",");
6665             addInstr(env, PPCInstr_XDirect(
6666                              mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
6667                                     : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
6668                              amCIA, cc, toFastEP));
6669          } else {
6670             /* .. very occasionally .. */
6671             /* We can't use chaining, so ask for an assisted transfer,
6672                as that's the only alternative that is allowable. */
6673             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst),
6674                                     IEndianess);
6675             addInstr(env, PPCInstr_XAssisted(r, amCIA, cc, Ijk_Boring));
6676          }
6677          return;
6678       }
6679 
6680       /* Case: assisted transfer to arbitrary address */
6681       switch (stmt->Ist.Exit.jk) {
6682          /* Keep this list in sync with that in iselNext below */
6683          case Ijk_ClientReq:
6684          case Ijk_EmFail:
6685          case Ijk_EmWarn:
6686          case Ijk_NoDecode:
6687          case Ijk_NoRedir:
6688          case Ijk_SigBUS:
6689          case Ijk_SigTRAP:
6690          case Ijk_Sys_syscall:
6691          case Ijk_InvalICache:
6692          {
6693             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst),
6694                                     IEndianess);
6695             addInstr(env, PPCInstr_XAssisted(r, amCIA, cc,
6696                                              stmt->Ist.Exit.jk));
6697             return;
6698          }
6699          default:
6700             break;
6701       }
6702 
6703       /* Do we ever expect to see any other kind? */
6704       goto stmt_fail;
6705    }
6706 
6707    default: break;
6708    }
6709   stmt_fail:
6710    ppIRStmt(stmt);
6711    vpanic("iselStmt(ppc)");
6712 }
6713 
6714 
6715 /*---------------------------------------------------------*/
6716 /*--- ISEL: Basic block terminators (Nexts)             ---*/
6717 /*---------------------------------------------------------*/
6718 
iselNext(ISelEnv * env,IRExpr * next,IRJumpKind jk,Int offsIP,IREndness IEndianess)6719 static void iselNext ( ISelEnv* env,
6720                        IRExpr* next, IRJumpKind jk, Int offsIP,
6721                        IREndness IEndianess)
6722 {
6723    if (vex_traceflags & VEX_TRACE_VCODE) {
6724       vex_printf( "\n-- PUT(%d) = ", offsIP);
6725       ppIRExpr( next );
6726       vex_printf( "; exit-");
6727       ppIRJumpKind(jk);
6728       vex_printf( "\n");
6729    }
6730 
6731    PPCCondCode always = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
6732 
6733    /* Case: boring transfer to known address */
6734    if (next->tag == Iex_Const) {
6735       IRConst* cdst = next->Iex.Const.con;
6736       vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
6737       if (jk == Ijk_Boring || jk == Ijk_Call) {
6738          /* Boring transfer to known address */
6739          PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
6740          if (env->chainingAllowed) {
6741             /* .. almost always true .. */
6742             /* Skip the event check at the dst if this is a forwards
6743                edge. */
6744             Bool toFastEP
6745                = env->mode64
6746                ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
6747                : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
6748             if (0) vex_printf("%s", toFastEP ? "X" : ".");
6749             addInstr(env, PPCInstr_XDirect(
6750                              env->mode64 ? (Addr64)cdst->Ico.U64
6751                                          : (Addr64)cdst->Ico.U32,
6752                              amCIA, always, toFastEP));
6753          } else {
6754             /* .. very occasionally .. */
6755             /* We can't use chaining, so ask for an assisted transfer,
6756                as that's the only alternative that is allowable. */
6757             HReg r = iselWordExpr_R(env, next, IEndianess);
6758             addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
6759                                              Ijk_Boring));
6760          }
6761          return;
6762       }
6763    }
6764 
6765    /* Case: call/return (==boring) transfer to any address */
6766    switch (jk) {
6767       case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
6768          HReg       r     = iselWordExpr_R(env, next, IEndianess);
6769          PPCAMode*  amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
6770          if (env->chainingAllowed) {
6771             addInstr(env, PPCInstr_XIndir(r, amCIA, always));
6772          } else {
6773             addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
6774                                              Ijk_Boring));
6775          }
6776          return;
6777       }
6778       default:
6779          break;
6780    }
6781 
6782    /* Case: assisted transfer to arbitrary address */
6783    switch (jk) {
6784       /* Keep this list in sync with that for Ist_Exit above */
6785       case Ijk_ClientReq:
6786       case Ijk_EmFail:
6787       case Ijk_EmWarn:
6788       case Ijk_NoDecode:
6789       case Ijk_NoRedir:
6790       case Ijk_SigBUS:
6791       case Ijk_SigTRAP:
6792       case Ijk_Sys_syscall:
6793       case Ijk_InvalICache:
6794       {
6795          HReg      r     = iselWordExpr_R(env, next, IEndianess);
6796          PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
6797          addInstr(env, PPCInstr_XAssisted(r, amCIA, always, jk));
6798          return;
6799       }
6800       default:
6801          break;
6802    }
6803 
6804    vex_printf( "\n-- PUT(%d) = ", offsIP);
6805    ppIRExpr( next );
6806    vex_printf( "; exit-");
6807    ppIRJumpKind(jk);
6808    vex_printf( "\n");
6809    vassert(0); // are we expecting any other kind?
6810 }
6811 
6812 
6813 /*---------------------------------------------------------*/
6814 /*--- Insn selector top-level                           ---*/
6815 /*---------------------------------------------------------*/
6816 
6817 /* 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)6818 HInstrArray* iselSB_PPC ( const IRSB* bb,
6819                           VexArch      arch_host,
6820                           const VexArchInfo* archinfo_host,
6821                           const VexAbiInfo*  vbi,
6822                           Int offs_Host_EvC_Counter,
6823                           Int offs_Host_EvC_FailAddr,
6824                           Bool chainingAllowed,
6825                           Bool addProfInc,
6826                           Addr max_ga)
6827 
6828 {
6829    Int       i, j;
6830    HReg      hregLo, hregMedLo, hregMedHi, hregHi;
6831    ISelEnv*  env;
6832    UInt      hwcaps_host = archinfo_host->hwcaps;
6833    Bool      mode64 = False;
6834    UInt      mask32, mask64;
6835    PPCAMode *amCounter, *amFailAddr;
6836    IREndness IEndianess;
6837 
6838    vassert(arch_host == VexArchPPC32 || arch_host == VexArchPPC64);
6839    mode64 = arch_host == VexArchPPC64;
6840 
6841    /* do some sanity checks,
6842     * Note: no 32-bit support for ISA 3.0
6843     */
6844    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
6845             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
6846             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
6847 
6848    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
6849             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
6850             | VEX_HWCAPS_PPC64_ISA2_07 | VEX_HWCAPS_PPC64_ISA3_0;
6851 
6852    if (mode64) {
6853       vassert((hwcaps_host & mask32) == 0);
6854    } else {
6855       vassert((hwcaps_host & mask64) == 0);
6856    }
6857 
6858    /* Check that the host's endianness is as expected. */
6859    vassert((archinfo_host->endness == VexEndnessBE) ||
6860 	   (archinfo_host->endness == VexEndnessLE));
6861 
6862    if (archinfo_host->endness == VexEndnessBE)
6863      IEndianess = Iend_BE;
6864    else
6865      IEndianess = Iend_LE;
6866 
6867    /* Make up an initial environment to use. */
6868    env = LibVEX_Alloc_inline(sizeof(ISelEnv));
6869    env->vreg_ctr = 0;
6870 
6871    /* Are we being ppc32 or ppc64? */
6872    env->mode64 = mode64;
6873 
6874    /* Set up output code array. */
6875    env->code = newHInstrArray();
6876 
6877    /* Copy BB's type env. */
6878    env->type_env = bb->tyenv;
6879 
6880    /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
6881     * change as we go along.
6882     *
6883     * vregmap2 and vregmap3 are only used in 32 bit mode
6884     * for supporting I128 in 32-bit mode
6885     */
6886    env->n_vregmap = bb->tyenv->types_used;
6887    env->vregmapLo    = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
6888    env->vregmapMedLo = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
6889    if (mode64) {
6890       env->vregmapMedHi = NULL;
6891       env->vregmapHi    = NULL;
6892    } else {
6893       env->vregmapMedHi = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
6894       env->vregmapHi    = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
6895    }
6896 
6897    /* and finally ... */
6898    env->chainingAllowed = chainingAllowed;
6899    env->max_ga          = max_ga;
6900    env->hwcaps          = hwcaps_host;
6901    env->previous_rm     = NULL;
6902    env->vbi             = vbi;
6903 
6904    /* For each IR temporary, allocate a suitably-kinded virtual
6905       register. */
6906    j = 0;
6907    for (i = 0; i < env->n_vregmap; i++) {
6908       hregLo = hregMedLo = hregMedHi = hregHi = INVALID_HREG;
6909       switch (bb->tyenv->types[i]) {
6910       case Ity_I1:
6911       case Ity_I8:
6912       case Ity_I16:
6913       case Ity_I32:
6914          if (mode64) {
6915             hregLo = mkHReg(True, HRcInt64, 0, j++);
6916          } else {
6917             hregLo = mkHReg(True, HRcInt32, 0, j++);
6918          }
6919          break;
6920       case Ity_I64:
6921          if (mode64) {
6922             hregLo    = mkHReg(True, HRcInt64, 0, j++);
6923          } else {
6924             hregLo    = mkHReg(True, HRcInt32, 0, j++);
6925             hregMedLo = mkHReg(True, HRcInt32, 0, j++);
6926          }
6927          break;
6928       case Ity_I128:
6929          if (mode64) {
6930             hregLo    = mkHReg(True, HRcInt64, 0, j++);
6931             hregMedLo = mkHReg(True, HRcInt64, 0, j++);
6932          } else {
6933             hregLo    = mkHReg(True, HRcInt32, 0, j++);
6934             hregMedLo = mkHReg(True, HRcInt32, 0, j++);
6935             hregMedHi = mkHReg(True, HRcInt32, 0, j++);
6936             hregHi    = mkHReg(True, HRcInt32, 0, j++);
6937          }
6938          break;
6939       case Ity_F32:
6940       case Ity_F64:
6941          hregLo = mkHReg(True, HRcFlt64, 0, j++);
6942          break;
6943       case Ity_F128:
6944       case Ity_V128:
6945          hregLo = mkHReg(True, HRcVec128, 0, j++);
6946          break;
6947       case Ity_D32:
6948       case Ity_D64:
6949          hregLo = mkHReg(True, HRcFlt64, 0, j++);
6950          break;
6951       case Ity_D128:
6952          hregLo    = mkHReg(True, HRcFlt64, 0, j++);
6953          hregMedLo = mkHReg(True, HRcFlt64, 0, j++);
6954          break;
6955       default:
6956          ppIRType(bb->tyenv->types[i]);
6957          vpanic("iselBB(ppc): IRTemp type");
6958       }
6959       env->vregmapLo[i]    = hregLo;
6960       env->vregmapMedLo[i] = hregMedLo;
6961       if (!mode64) {
6962          env->vregmapMedHi[i] = hregMedHi;
6963          env->vregmapHi[i]    = hregHi;
6964       }
6965    }
6966    env->vreg_ctr = j;
6967 
6968    /* The very first instruction must be an event check. */
6969    amCounter  = PPCAMode_IR(offs_Host_EvC_Counter, hregPPC_GPR31(mode64));
6970    amFailAddr = PPCAMode_IR(offs_Host_EvC_FailAddr, hregPPC_GPR31(mode64));
6971    addInstr(env, PPCInstr_EvCheck(amCounter, amFailAddr));
6972 
6973    /* Possibly a block counter increment (for profiling).  At this
6974       point we don't know the address of the counter, so just pretend
6975       it is zero.  It will have to be patched later, but before this
6976       translation is used, by a call to LibVEX_patchProfCtr. */
6977    if (addProfInc) {
6978       addInstr(env, PPCInstr_ProfInc());
6979    }
6980 
6981    /* Ok, finally we can iterate over the statements. */
6982    for (i = 0; i < bb->stmts_used; i++)
6983       iselStmt(env, bb->stmts[i], IEndianess);
6984 
6985    iselNext(env, bb->next, bb->jumpkind, bb->offsIP, IEndianess);
6986 
6987    /* record the number of vregs we used. */
6988    env->code->n_vregs = env->vreg_ctr;
6989    return env->code;
6990 }
6991 
6992 
6993 /*---------------------------------------------------------------*/
6994 /*--- end                                     host_ppc_isel.c ---*/
6995 /*---------------------------------------------------------------*/
6996