• 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-2013 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       VexAbiInfo*  vbi;
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 = mkHReg(env->vreg_ctr, HRcGPR(env->mode64),
345                      True/*virtual reg*/);
346    env->vreg_ctr++;
347    return reg;
348 }
349 
newVRegF(ISelEnv * env)350 static HReg newVRegF ( ISelEnv* env )
351 {
352    HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
353    env->vreg_ctr++;
354    return reg;
355 }
356 
newVRegV(ISelEnv * env)357 static HReg newVRegV ( ISelEnv* env )
358 {
359    HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
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, IRExpr* e );
383 static HReg          iselWordExpr_R     ( ISelEnv* env, IRExpr* e );
384 
385 /* 32-bit mode: Compute an I8/I16/I32 into a RH
386                 (reg-or-halfword-immediate).
387    64-bit mode: Compute an I8/I16/I32/I64 into a RH
388                 (reg-or-halfword-immediate).
389    It's important to specify whether the immediate is to be regarded
390    as signed or not.  If yes, this will never return -32768 as an
391    immediate; this guaranteed that all signed immediates that are
392    return can have their sign inverted if need be.
393 */
394 static PPCRH*        iselWordExpr_RH_wrk ( ISelEnv* env,
395                                            Bool syned, IRExpr* e );
396 static PPCRH*        iselWordExpr_RH     ( ISelEnv* env,
397                                            Bool syned, IRExpr* e );
398 
399 /* 32-bit mode: compute an I32 into a RI (reg or 32-bit immediate).
400    64-bit mode: compute an I64 into a RI (reg or 64-bit immediate). */
401 static PPCRI*        iselWordExpr_RI_wrk ( ISelEnv* env, IRExpr* e );
402 static PPCRI*        iselWordExpr_RI     ( ISelEnv* env, IRExpr* e );
403 
404 /* In 32 bit mode ONLY, compute an I8 into a
405    reg-or-5-bit-unsigned-immediate, the latter being an immediate in
406    the range 1 .. 31 inclusive.  Used for doing shift amounts. */
407 static PPCRH*        iselWordExpr_RH5u_wrk ( ISelEnv* env, IRExpr* e );
408 static PPCRH*        iselWordExpr_RH5u     ( ISelEnv* env, IRExpr* e );
409 
410 /* In 64-bit mode ONLY, compute an I8 into a
411    reg-or-6-bit-unsigned-immediate, the latter being an immediate in
412    the range 1 .. 63 inclusive.  Used for doing shift amounts. */
413 static PPCRH*        iselWordExpr_RH6u_wrk ( ISelEnv* env, IRExpr* e );
414 static PPCRH*        iselWordExpr_RH6u     ( ISelEnv* env, IRExpr* e );
415 
416 /* 32-bit mode: compute an I32 into an AMode.
417    64-bit mode: compute an I64 into an AMode.
418 
419    Requires to know (xferTy) the type of data to be loaded/stored
420    using this amode.  That is so that, for 64-bit code generation, any
421    PPCAMode_IR returned will have an index (immediate offset) field
422    that is guaranteed to be 4-aligned, if there is any chance that the
423    amode is to be used in ld/ldu/lda/std/stdu.
424 
425    Since there are no such restrictions on 32-bit insns, xferTy is
426    ignored for 32-bit code generation. */
427 static PPCAMode*     iselWordExpr_AMode_wrk ( ISelEnv* env, IRExpr* e, IRType xferTy );
428 static PPCAMode*     iselWordExpr_AMode     ( ISelEnv* env, IRExpr* e, IRType xferTy );
429 
430 static void iselInt128Expr_to_32x4_wrk ( HReg* rHi, HReg* rMedHi,
431                                          HReg* rMedLo, HReg* rLo,
432                                          ISelEnv* env, IRExpr* e );
433 static void iselInt128Expr_to_32x4     ( HReg* rHi, HReg* rMedHi,
434                                          HReg* rMedLo, HReg* rLo,
435                                          ISelEnv* env, IRExpr* e );
436 
437 
438 /* 32-bit mode ONLY: compute an I64 into a GPR pair. */
439 static void          iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
440                                          ISelEnv* env, IRExpr* e );
441 static void          iselInt64Expr     ( HReg* rHi, HReg* rLo,
442                                          ISelEnv* env, IRExpr* e );
443 
444 /* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
445 static void          iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
446                                           ISelEnv* env, IRExpr* e );
447 static void          iselInt128Expr     ( HReg* rHi, HReg* rLo,
448                                           ISelEnv* env, IRExpr* e );
449 
450 static PPCCondCode   iselCondCode_wrk ( ISelEnv* env, IRExpr* e );
451 static PPCCondCode   iselCondCode     ( ISelEnv* env, IRExpr* e );
452 
453 static HReg          iselDblExpr_wrk ( ISelEnv* env, IRExpr* e );
454 static HReg          iselDblExpr     ( ISelEnv* env, IRExpr* e );
455 
456 static HReg          iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
457 static HReg          iselFltExpr     ( ISelEnv* env, IRExpr* e );
458 
459 static HReg          iselVecExpr_wrk ( ISelEnv* env, IRExpr* e );
460 static HReg          iselVecExpr     ( ISelEnv* env, IRExpr* e );
461 
462 /* 64-bit mode ONLY. */
463 static HReg          iselDfp32Expr_wrk ( ISelEnv* env, IRExpr* e );
464 static HReg          iselDfp32Expr     ( ISelEnv* env, IRExpr* e );
465 static HReg          iselDfp64Expr_wrk ( ISelEnv* env, IRExpr* e );
466 static HReg          iselDfp64Expr     ( ISelEnv* env, IRExpr* e );
467 
468 /* 64-bit mode ONLY: compute an D128 into a GPR64 pair. */
469 static void iselDfp128Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env,
470                                  IRExpr* e );
471 static void iselDfp128Expr     ( HReg* rHi, HReg* rLo, ISelEnv* env,
472                                  IRExpr* e );
473 
474 /*---------------------------------------------------------*/
475 /*--- ISEL: Misc helpers                                ---*/
476 /*---------------------------------------------------------*/
477 
478 /* Make an int reg-reg move. */
479 
mk_iMOVds_RR(HReg r_dst,HReg r_src)480 static PPCInstr* mk_iMOVds_RR ( HReg r_dst, HReg r_src )
481 {
482    vassert(hregClass(r_dst) == hregClass(r_src));
483    vassert(hregClass(r_src) ==  HRcInt32 ||
484            hregClass(r_src) ==  HRcInt64);
485    return PPCInstr_Alu(Palu_OR, r_dst, r_src, PPCRH_Reg(r_src));
486 }
487 
488 /* Advance/retreat %r1 by n. */
489 
add_to_sp(ISelEnv * env,UInt n)490 static void add_to_sp ( ISelEnv* env, UInt n )
491 {
492    HReg sp = StackFramePtr(env->mode64);
493    vassert(n <= 1024 && (n%16) == 0);
494    addInstr(env, PPCInstr_Alu( Palu_ADD, sp, sp,
495                                PPCRH_Imm(True,toUShort(n)) ));
496 }
497 
sub_from_sp(ISelEnv * env,UInt n)498 static void sub_from_sp ( ISelEnv* env, UInt n )
499 {
500    HReg sp = StackFramePtr(env->mode64);
501    vassert(n <= 1024 && (n%16) == 0);
502    addInstr(env, PPCInstr_Alu( Palu_SUB, sp, sp,
503                                PPCRH_Imm(True,toUShort(n)) ));
504 }
505 
506 /*
507   returns a quadword aligned address on the stack
508    - copies SP, adds 16bytes, aligns to quadword.
509   use sub_from_sp(32) before calling this,
510   as expects to have 32 bytes to play with.
511 */
get_sp_aligned16(ISelEnv * env)512 static HReg get_sp_aligned16 ( ISelEnv* env )
513 {
514    HReg       r = newVRegI(env);
515    HReg align16 = newVRegI(env);
516    addInstr(env, mk_iMOVds_RR(r, StackFramePtr(env->mode64)));
517    // add 16
518    addInstr(env, PPCInstr_Alu( Palu_ADD, r, r,
519                                PPCRH_Imm(True,toUShort(16)) ));
520    // mask to quadword
521    addInstr(env,
522             PPCInstr_LI(align16, 0xFFFFFFFFFFFFFFF0ULL, env->mode64));
523    addInstr(env, PPCInstr_Alu(Palu_AND, r,r, PPCRH_Reg(align16)));
524    return r;
525 }
526 
527 
528 
529 /* Load 2*I32 regs to fp reg */
mk_LoadRR32toFPR(ISelEnv * env,HReg r_srcHi,HReg r_srcLo)530 static HReg mk_LoadRR32toFPR ( ISelEnv* env,
531                                HReg r_srcHi, HReg r_srcLo )
532 {
533    HReg fr_dst = newVRegF(env);
534    PPCAMode *am_addr0, *am_addr1;
535 
536    vassert(!env->mode64);
537    vassert(hregClass(r_srcHi) == HRcInt32);
538    vassert(hregClass(r_srcLo) == HRcInt32);
539 
540    sub_from_sp( env, 16 );        // Move SP down 16 bytes
541    am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
542    am_addr1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
543 
544    // store hi,lo as Ity_I32's
545    addInstr(env, PPCInstr_Store( 4, am_addr0, r_srcHi, env->mode64 ));
546    addInstr(env, PPCInstr_Store( 4, am_addr1, r_srcLo, env->mode64 ));
547 
548    // load as float
549    addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));
550 
551    add_to_sp( env, 16 );          // Reset SP
552    return fr_dst;
553 }
554 
555 /* Load I64 reg to fp reg */
mk_LoadR64toFPR(ISelEnv * env,HReg r_src)556 static HReg mk_LoadR64toFPR ( ISelEnv* env, HReg r_src )
557 {
558    HReg fr_dst = newVRegF(env);
559    PPCAMode *am_addr0;
560 
561    vassert(env->mode64);
562    vassert(hregClass(r_src) == HRcInt64);
563 
564    sub_from_sp( env, 16 );        // Move SP down 16 bytes
565    am_addr0 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
566 
567    // store as Ity_I64
568    addInstr(env, PPCInstr_Store( 8, am_addr0, r_src, env->mode64 ));
569 
570    // load as float
571    addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_dst, am_addr0));
572 
573    add_to_sp( env, 16 );          // Reset SP
574    return fr_dst;
575 }
576 
577 
578 /* Given an amode, return one which references 4 bytes further
579    along. */
580 
advance4(ISelEnv * env,PPCAMode * am)581 static PPCAMode* advance4 ( ISelEnv* env, PPCAMode* am )
582 {
583    PPCAMode* am4 = dopyPPCAMode( am );
584    if (am4->tag == Pam_IR
585        && am4->Pam.IR.index + 4 <= 32767) {
586       am4->Pam.IR.index += 4;
587    } else {
588       vpanic("advance4(ppc,host)");
589    }
590    return am4;
591 }
592 
593 
594 /* Given a guest-state array descriptor, an index expression and a
595    bias, generate a PPCAMode pointing at the relevant piece of
596    guest state.  */
597 static
genGuestArrayOffset(ISelEnv * env,IRRegArray * descr,IRExpr * off,Int bias)598 PPCAMode* genGuestArrayOffset ( ISelEnv* env, IRRegArray* descr,
599                                 IRExpr* off, Int bias )
600 {
601    HReg rtmp, roff;
602    Int  elemSz = sizeofIRType(descr->elemTy);
603    Int  nElems = descr->nElems;
604    Int  shift  = 0;
605 
606    /* Throw out any cases we don't need.  In theory there might be a
607       day where we need to handle others, but not today. */
608 
609    if (nElems != 16 && nElems != 32)
610       vpanic("genGuestArrayOffset(ppc host)(1)");
611 
612    switch (elemSz) {
613       case 4:  shift = 2; break;
614       case 8:  shift = 3; break;
615       default: vpanic("genGuestArrayOffset(ppc host)(2)");
616    }
617 
618    if (bias < -100 || bias > 100) /* somewhat arbitrarily */
619       vpanic("genGuestArrayOffset(ppc host)(3)");
620    if (descr->base < 0 || descr->base > 5000) /* somewhat arbitrarily */
621       vpanic("genGuestArrayOffset(ppc host)(4)");
622 
623    /* Compute off into a reg, %off.  Then return:
624 
625          addi %tmp, %off, bias (if bias != 0)
626          andi %tmp, nElems-1
627          sldi %tmp, shift
628          addi %tmp, %tmp, base
629          ... Baseblockptr + %tmp ...
630    */
631    roff = iselWordExpr_R(env, off);
632    rtmp = newVRegI(env);
633    addInstr(env, PPCInstr_Alu(
634                     Palu_ADD,
635                     rtmp, roff,
636                     PPCRH_Imm(True/*signed*/, toUShort(bias))));
637    addInstr(env, PPCInstr_Alu(
638                     Palu_AND,
639                     rtmp, rtmp,
640                     PPCRH_Imm(False/*unsigned*/, toUShort(nElems-1))));
641    addInstr(env, PPCInstr_Shft(
642                     Pshft_SHL,
643                     env->mode64 ? False : True/*F:64-bit, T:32-bit shift*/,
644                     rtmp, rtmp,
645                     PPCRH_Imm(False/*unsigned*/, toUShort(shift))));
646    addInstr(env, PPCInstr_Alu(
647                     Palu_ADD,
648                     rtmp, rtmp,
649                     PPCRH_Imm(True/*signed*/, toUShort(descr->base))));
650    return
651       PPCAMode_RR( GuestStatePtr(env->mode64), rtmp );
652 }
653 
654 
655 /*---------------------------------------------------------*/
656 /*--- ISEL: Function call helpers                       ---*/
657 /*---------------------------------------------------------*/
658 
659 /* Used only in doHelperCall.  See big comment in doHelperCall re
660    handling of register-parameter args.  This function figures out
661    whether evaluation of an expression might require use of a fixed
662    register.  If in doubt return True (safe but suboptimal).
663 */
664 static
mightRequireFixedRegs(IRExpr * e)665 Bool mightRequireFixedRegs ( IRExpr* e )
666 {
667    switch (e->tag) {
668    case Iex_RdTmp: case Iex_Const: case Iex_Get:
669       return False;
670    default:
671       return True;
672    }
673 }
674 
675 
676 /* Do a complete function call.  |guard| is a Ity_Bit expression
677    indicating whether or not the call happens.  If guard==NULL, the
678    call is unconditional.  |retloc| is set to indicate where the
679    return value is after the call.  The caller (of this fn) must
680    generate code to add |stackAdjustAfterCall| to the stack pointer
681    after the call is done. */
682 
683 static
doHelperCall(UInt * stackAdjustAfterCall,RetLoc * retloc,ISelEnv * env,IRExpr * guard,IRCallee * cee,IRType retTy,IRExpr ** args)684 void doHelperCall ( /*OUT*/UInt*   stackAdjustAfterCall,
685                     /*OUT*/RetLoc* retloc,
686                     ISelEnv* env,
687                     IRExpr* guard,
688                     IRCallee* cee, IRType retTy, IRExpr** args )
689 {
690    PPCCondCode cc;
691    HReg        argregs[PPC_N_REGPARMS];
692    HReg        tmpregs[PPC_N_REGPARMS];
693    Bool        go_fast;
694    Int         n_args, i, argreg;
695    UInt        argiregs;
696    Bool        mode64 = env->mode64;
697 
698    /* Set default returns.  We'll update them later if needed. */
699    *stackAdjustAfterCall = 0;
700    *retloc               = mk_RetLoc_INVALID();
701 
702    /* These are used for cross-checking that IR-level constraints on
703       the use of IRExpr_VECRET() and IRExpr_BBPTR() are observed. */
704    UInt nVECRETs = 0;
705    UInt nBBPTRs  = 0;
706 
707    /* Do we need to force use of an odd-even reg pair for 64-bit args?
708       JRS 31-07-2013: is this still relevant, now that we are not
709       generating code for 32-bit AIX ? */
710    Bool regalign_int64s
711       = (!mode64) && env->vbi->host_ppc32_regalign_int64_args;
712 
713    /* Marshal args for a call and do the call.
714 
715       This function only deals with a tiny set of possibilities, which
716       cover all helpers in practice.  The restrictions are that only
717       arguments in registers are supported, hence only PPC_N_REGPARMS x
718       (mode32:32 | mode64:64) integer bits in total can be passed.
719       In fact the only supported arg type is (mode32:I32 | mode64:I64).
720 
721       The return type can be I{64,32,16,8} or V{128,256}.  In the
722       latter two cases, it is expected that |args| will contain the
723       special node IRExpr_VECRET(), in which case this routine
724       generates code to allocate space on the stack for the vector
725       return value.  Since we are not passing any scalars on the
726       stack, it is enough to preallocate the return space before
727       marshalling any arguments, in this case.
728 
729       |args| may also contain IRExpr_BBPTR(), in which case the value
730       in the guest state pointer register is passed as the
731       corresponding argument.
732 
733       Generating code which is both efficient and correct when
734       parameters are to be passed in registers is difficult, for the
735       reasons elaborated in detail in comments attached to
736       doHelperCall() in priv/host-x86/isel.c.  Here, we use a variant
737       of the method described in those comments.
738 
739       The problem is split into two cases: the fast scheme and the
740       slow scheme.  In the fast scheme, arguments are computed
741       directly into the target (real) registers.  This is only safe
742       when we can be sure that computation of each argument will not
743       trash any real registers set by computation of any other
744       argument.
745 
746       In the slow scheme, all args are first computed into vregs, and
747       once they are all done, they are moved to the relevant real
748       regs.  This always gives correct code, but it also gives a bunch
749       of vreg-to-rreg moves which are usually redundant but are hard
750       for the register allocator to get rid of.
751 
752       To decide which scheme to use, all argument expressions are
753       first examined.  If they are all so simple that it is clear they
754       will be evaluated without use of any fixed registers, use the
755       fast scheme, else use the slow scheme.  Note also that only
756       unconditional calls may use the fast scheme, since having to
757       compute a condition expression could itself trash real
758       registers.
759 
760       Note this requires being able to examine an expression and
761       determine whether or not evaluation of it might use a fixed
762       register.  That requires knowledge of how the rest of this insn
763       selector works.  Currently just the following 3 are regarded as
764       safe -- hopefully they cover the majority of arguments in
765       practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
766    */
767 
768    /* Note that the cee->regparms field is meaningless on PPC32/64 host
769       (since there is only one calling convention) and so we always
770       ignore it. */
771 
772    n_args = 0;
773    for (i = 0; args[i]; i++)
774       n_args++;
775 
776    if (n_args > PPC_N_REGPARMS) {
777       vpanic("doHelperCall(PPC): cannot currently handle > 8 args");
778       // PPC_N_REGPARMS
779    }
780 
781    /* This is kind of stupid .. the arrays are sized as PPC_N_REGPARMS
782       but we then assume that that value is 8. */
783    vassert(PPC_N_REGPARMS == 8);
784 
785    argregs[0] = hregPPC_GPR3(mode64);
786    argregs[1] = hregPPC_GPR4(mode64);
787    argregs[2] = hregPPC_GPR5(mode64);
788    argregs[3] = hregPPC_GPR6(mode64);
789    argregs[4] = hregPPC_GPR7(mode64);
790    argregs[5] = hregPPC_GPR8(mode64);
791    argregs[6] = hregPPC_GPR9(mode64);
792    argregs[7] = hregPPC_GPR10(mode64);
793    argiregs = 0;
794 
795    tmpregs[0] = tmpregs[1] = tmpregs[2] =
796    tmpregs[3] = tmpregs[4] = tmpregs[5] =
797    tmpregs[6] = tmpregs[7] = INVALID_HREG;
798 
799    /* First decide which scheme (slow or fast) is to be used.  First
800       assume the fast scheme, and select slow if any contraindications
801       (wow) appear. */
802 
803    go_fast = True;
804 
805    /* We'll need space on the stack for the return value.  Avoid
806       possible complications with nested calls by using the slow
807       scheme. */
808    if (retTy == Ity_V128 || retTy == Ity_V256)
809       go_fast = False;
810 
811    if (go_fast && guard) {
812       if (guard->tag == Iex_Const
813           && guard->Iex.Const.con->tag == Ico_U1
814           && guard->Iex.Const.con->Ico.U1 == True) {
815          /* unconditional */
816       } else {
817          /* Not manifestly unconditional -- be conservative. */
818          go_fast = False;
819       }
820    }
821 
822    if (go_fast) {
823       for (i = 0; i < n_args; i++) {
824          IRExpr* arg = args[i];
825          if (UNLIKELY(arg->tag == Iex_BBPTR)) {
826             /* that's OK */
827          }
828          else if (UNLIKELY(arg->tag == Iex_VECRET)) {
829             /* This implies ill-formed IR, since if the IR was
830                well-formed, the return-type test above would have
831                filtered it out. */
832             vpanic("doHelperCall(PPC): invalid IR");
833          }
834          else if (mightRequireFixedRegs(arg)) {
835             go_fast = False;
836             break;
837          }
838       }
839    }
840 
841    /* At this point the scheme to use has been established.  Generate
842       code to get the arg values into the argument rregs. */
843 
844    if (go_fast) {
845 
846       /* FAST SCHEME */
847       argreg = 0;
848 
849       for (i = 0; i < n_args; i++) {
850          IRExpr* arg = args[i];
851          vassert(argreg < PPC_N_REGPARMS);
852 
853          if (arg->tag == Iex_BBPTR) {
854             argiregs |= (1 << (argreg+3));
855             addInstr(env, mk_iMOVds_RR( argregs[argreg],
856                                         GuestStatePtr(mode64) ));
857             argreg++;
858          } else {
859             vassert(arg->tag != Iex_VECRET);
860             IRType ty = typeOfIRExpr(env->type_env, arg);
861             vassert(ty == Ity_I32 || ty == Ity_I64);
862             if (!mode64) {
863                if (ty == Ity_I32) {
864                   argiregs |= (1 << (argreg+3));
865                   addInstr(env,
866                            mk_iMOVds_RR( argregs[argreg],
867                                          iselWordExpr_R(env, arg) ));
868                } else { // Ity_I64 in 32-bit mode
869                   HReg rHi, rLo;
870                   if (regalign_int64s && (argreg%2) == 1)
871                                  // ppc32 ELF abi spec for passing LONG_LONG
872                      argreg++;   // XXX: odd argreg => even rN
873                   vassert(argreg < PPC_N_REGPARMS-1);
874                   iselInt64Expr(&rHi,&rLo, env, arg);
875                   argiregs |= (1 << (argreg+3));
876                   addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));
877                   argiregs |= (1 << (argreg+3));
878                   addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));
879                }
880             } else { // mode64
881                argiregs |= (1 << (argreg+3));
882                addInstr(env, mk_iMOVds_RR( argregs[argreg],
883                                            iselWordExpr_R(env, arg) ));
884             }
885             argreg++;
886          } /* if (arg == IRExprP__BBPR) */
887       }
888 
889       /* Fast scheme only applies for unconditional calls.  Hence: */
890       cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
891 
892    } else {
893 
894       /* SLOW SCHEME; move via temporaries */
895       argreg = 0;
896 
897       /* If we have a vector return type, allocate a place for it on
898          the stack and record its address.  Rather than figure out the
899          complexities of PPC{32,64} ELF ABI stack frame layout, simply
900          drop the SP by 1024 and allocate the return point in the
901          middle.  I think this should comfortably clear any ABI
902          mandated register save areas.  Note that it doesn't maintain
903          the backchain as it should, since we're not doing st{d,w}u to
904          adjust the SP, but .. that doesn't seem to be a big deal.
905          Since we're not expecting to have to unwind out of here. */
906       HReg r_vecRetAddr = INVALID_HREG;
907       if (retTy == Ity_V128) {
908          r_vecRetAddr = newVRegI(env);
909          sub_from_sp(env, 512);
910          addInstr(env, mk_iMOVds_RR( r_vecRetAddr, StackFramePtr(mode64) ));
911          sub_from_sp(env, 512);
912       }
913       else if (retTy == Ity_V256) {
914          vassert(0); //ATC
915          r_vecRetAddr = newVRegI(env);
916          sub_from_sp(env, 512);
917          addInstr(env, mk_iMOVds_RR( r_vecRetAddr, StackFramePtr(mode64) ));
918          sub_from_sp(env, 512);
919       }
920 
921       vassert(n_args >= 0 && n_args <= 8);
922       for (i = 0; i < n_args; i++) {
923          IRExpr* arg = args[i];
924          vassert(argreg < PPC_N_REGPARMS);
925          if (UNLIKELY(arg->tag == Iex_BBPTR)) {
926             tmpregs[argreg] = newVRegI(env);
927             addInstr(env, mk_iMOVds_RR( tmpregs[argreg],
928                                         GuestStatePtr(mode64) ));
929             nBBPTRs++;
930          }
931          else if (UNLIKELY(arg->tag == Iex_VECRET)) {
932             /* We stashed the address of the return slot earlier, so just
933                retrieve it now. */
934             vassert(!hregIsInvalid(r_vecRetAddr));
935             tmpregs[i] = r_vecRetAddr;
936             nVECRETs++;
937          }
938          else {
939             IRType ty = typeOfIRExpr(env->type_env, arg);
940             vassert(ty == Ity_I32 || ty == Ity_I64);
941             if (!mode64) {
942                if (ty == Ity_I32) {
943                   tmpregs[argreg] = iselWordExpr_R(env, arg);
944                } else { // Ity_I64 in 32-bit mode
945                   HReg rHi, rLo;
946                   if (regalign_int64s && (argreg%2) == 1)
947                                 // ppc32 ELF abi spec for passing LONG_LONG
948                      argreg++;  // XXX: odd argreg => even rN
949                   vassert(argreg < PPC_N_REGPARMS-1);
950                   iselInt64Expr(&rHi,&rLo, env, arg);
951                   tmpregs[argreg++] = rHi;
952                   tmpregs[argreg]   = rLo;
953                }
954             } else { // mode64
955                tmpregs[argreg] = iselWordExpr_R(env, arg);
956             }
957          }
958          argreg++;
959       }
960 
961       /* Now we can compute the condition.  We can't do it earlier
962          because the argument computations could trash the condition
963          codes.  Be a bit clever to handle the common case where the
964          guard is 1:Bit. */
965       cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
966       if (guard) {
967          if (guard->tag == Iex_Const
968              && guard->Iex.Const.con->tag == Ico_U1
969              && guard->Iex.Const.con->Ico.U1 == True) {
970             /* unconditional -- do nothing */
971          } else {
972             cc = iselCondCode( env, guard );
973          }
974       }
975 
976       /* Move the args to their final destinations. */
977       for (i = 0; i < argreg; i++) {
978          if (hregIsInvalid(tmpregs[i]))  // Skip invalid regs
979             continue;
980          /* None of these insns, including any spill code that might
981             be generated, may alter the condition codes. */
982          argiregs |= (1 << (i+3));
983          addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) );
984       }
985 
986    }
987 
988    /* Do final checks, set the return values, and generate the call
989       instruction proper. */
990    if (retTy == Ity_V128 || retTy == Ity_V256) {
991       vassert(nVECRETs == 1);
992    } else {
993       vassert(nVECRETs == 0);
994    }
995 
996    vassert(nBBPTRs == 0 || nBBPTRs == 1);
997 
998    vassert(*stackAdjustAfterCall == 0);
999    vassert(is_RetLoc_INVALID(*retloc));
1000    switch (retTy) {
1001       case Ity_INVALID:
1002          /* Function doesn't return a value. */
1003          *retloc = mk_RetLoc_simple(RLPri_None);
1004          break;
1005       case Ity_I64:
1006          *retloc = mk_RetLoc_simple(mode64 ? RLPri_Int : RLPri_2Int);
1007          break;
1008       case Ity_I32: case Ity_I16: case Ity_I8:
1009          *retloc = mk_RetLoc_simple(RLPri_Int);
1010          break;
1011       case Ity_V128:
1012          /* Result is 512 bytes up the stack, and after it has been
1013             retrieved, adjust SP upwards by 1024. */
1014          *retloc = mk_RetLoc_spRel(RLPri_V128SpRel, 512);
1015          *stackAdjustAfterCall = 1024;
1016          break;
1017       case Ity_V256:
1018          vassert(0); // ATC
1019          /* Ditto */
1020          *retloc = mk_RetLoc_spRel(RLPri_V256SpRel, 512);
1021          *stackAdjustAfterCall = 1024;
1022          break;
1023       default:
1024          /* IR can denote other possible return types, but we don't
1025             handle those here. */
1026          vassert(0);
1027    }
1028 
1029    /* Finally, generate the call itself.  This needs the *retloc value
1030       set in the switch above, which is why it's at the end. */
1031 
1032    ULong target = mode64 ? Ptr_to_ULong(cee->addr)
1033                          : toUInt(Ptr_to_ULong(cee->addr));
1034    addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs, *retloc ));
1035 }
1036 
1037 
1038 /*---------------------------------------------------------*/
1039 /*--- ISEL: FP rounding mode helpers                    ---*/
1040 /*---------------------------------------------------------*/
1041 
1042 ///* Set FPU's rounding mode to the default */
1043 //static
1044 //void set_FPU_rounding_default ( ISelEnv* env )
1045 //{
1046 //   HReg fr_src = newVRegF(env);
1047 //   HReg r_src  = newVRegI(env);
1048 //
1049 //   /* Default rounding mode = 0x0
1050 //      Only supporting the rounding-mode bits - the rest of FPSCR is 0x0
1051 //       - so we can set the whole register at once (faster)
1052 //      note: upper 32 bits ignored by FpLdFPSCR
1053 //   */
1054 //   addInstr(env, PPCInstr_LI(r_src, 0x0, env->mode64));
1055 //   if (env->mode64) {
1056 //      fr_src = mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
1057 //   } else {
1058 //      fr_src = mk_LoadRR32toFPR( env, r_src, r_src ); // 2*I32 -> F64
1059 //   }
1060 //   addInstr(env, PPCInstr_FpLdFPSCR( fr_src ));
1061 //}
1062 
1063 /* Convert IR rounding mode to PPC encoding */
roundModeIRtoPPC(ISelEnv * env,HReg r_rmIR)1064 static HReg roundModeIRtoPPC ( ISelEnv* env, HReg r_rmIR )
1065 {
1066    /*
1067    rounding mode                     | PPC  |  IR
1068    -----------------------------------------------
1069    to nearest, ties to even          | 000  | 000
1070    to zero                           | 001  | 011
1071    to +infinity                      | 010  | 010
1072    to -infinity                      | 011  | 001
1073    +++++ Below are the extended rounding modes for decimal floating point +++++
1074    to nearest, ties away from 0      | 100  | 100
1075    to nearest, ties toward 0         | 101  | 111
1076    to away from 0                    | 110  | 110
1077    to prepare for shorter precision  | 111  | 101
1078    */
1079    HReg r_rmPPC = newVRegI(env);
1080    HReg r_tmp1  = newVRegI(env);
1081    HReg r_tmp2  = newVRegI(env);
1082 
1083    vassert(hregClass(r_rmIR) == HRcGPR(env->mode64));
1084 
1085    // r_rmPPC = XOR(r_rmIR, r_rmIR << 1) & 3
1086    //
1087    // slwi  tmp1,    r_rmIR, 1
1088    // xor   tmp1,    r_rmIR, tmp1
1089    // andi  r_rmPPC, tmp1, 3
1090 
1091    addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1092                                r_tmp1, r_rmIR, PPCRH_Imm(False,1)));
1093 
1094    addInstr( env, PPCInstr_Alu( Palu_AND,
1095                                 r_tmp2, r_tmp1, PPCRH_Imm( False, 3 ) ) );
1096 
1097    addInstr( env, PPCInstr_Alu( Palu_XOR,
1098                                 r_rmPPC, r_rmIR, PPCRH_Reg( r_tmp2 ) ) );
1099 
1100    return r_rmPPC;
1101 }
1102 
1103 
1104 /* Set the FPU's rounding mode: 'mode' is an I32-typed expression
1105    denoting a value in the range 0 .. 7, indicating a round mode
1106    encoded as per type IRRoundingMode.  Set the PPC FPSCR to have the
1107    same rounding.  When the dfp_rm arg is True, set the decimal
1108    floating point rounding mode bits (29:31); otherwise, set the
1109    binary floating point rounding mode bits (62:63).
1110 
1111    For speed & simplicity, we're setting the *entire* FPSCR here.
1112 
1113    Setting the rounding mode is expensive.  So this function tries to
1114    avoid repeatedly setting the rounding mode to the same thing by
1115    first comparing 'mode' to the 'mode' tree supplied in the previous
1116    call to this function, if any.  (The previous value is stored in
1117    env->previous_rm.)  If 'mode' is a single IR temporary 't' and
1118    env->previous_rm is also just 't', then the setting is skipped.
1119 
1120    This is safe because of the SSA property of IR: an IR temporary can
1121    only be defined once and so will have the same value regardless of
1122    where it appears in the block.  Cool stuff, SSA.
1123 
1124    A safety condition: all attempts to set the RM must be aware of
1125    this mechanism - by being routed through the functions here.
1126 
1127    Of course this only helps if blocks where the RM is set more than
1128    once and it is set to the same value each time, *and* that value is
1129    held in the same IR temporary each time.  In order to assure the
1130    latter as much as possible, the IR optimiser takes care to do CSE
1131    on any block with any sign of floating point activity.
1132 */
1133 static
_set_FPU_rounding_mode(ISelEnv * env,IRExpr * mode,Bool dfp_rm)1134 void _set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode, Bool dfp_rm )
1135 {
1136    HReg fr_src = newVRegF(env);
1137    HReg r_src;
1138 
1139    vassert(typeOfIRExpr(env->type_env,mode) == Ity_I32);
1140 
1141    /* Do we need to do anything? */
1142    if (env->previous_rm
1143        && env->previous_rm->tag == Iex_RdTmp
1144        && mode->tag == Iex_RdTmp
1145        && env->previous_rm->Iex.RdTmp.tmp == mode->Iex.RdTmp.tmp) {
1146       /* no - setting it to what it was before.  */
1147       vassert(typeOfIRExpr(env->type_env, env->previous_rm) == Ity_I32);
1148       return;
1149    }
1150 
1151    /* No luck - we better set it, and remember what we set it to. */
1152    env->previous_rm = mode;
1153 
1154    /* Only supporting the rounding-mode bits - the rest of FPSCR is
1155       0x0 - so we can set the whole register at once (faster). */
1156 
1157    // Resolve rounding mode and convert to PPC representation
1158    r_src = roundModeIRtoPPC( env, iselWordExpr_R(env, mode) );
1159 
1160    // gpr -> fpr
1161    if (env->mode64) {
1162       if (dfp_rm) {
1163          HReg r_tmp1 = newVRegI( env );
1164          addInstr( env,
1165                    PPCInstr_Shft( Pshft_SHL, False/*64bit shift*/,
1166                                   r_tmp1, r_src, PPCRH_Imm( False, 32 ) ) );
1167          fr_src = mk_LoadR64toFPR( env, r_tmp1 );
1168       } else {
1169          fr_src = mk_LoadR64toFPR( env, r_src ); // 1*I64 -> F64
1170       }
1171    } else {
1172       if (dfp_rm) {
1173          HReg r_zero = newVRegI( env );
1174          addInstr( env, PPCInstr_LI( r_zero, 0, env->mode64 ) );
1175          fr_src = mk_LoadRR32toFPR( env, r_src, r_zero );
1176       } else {
1177          fr_src = mk_LoadRR32toFPR( env, r_src, r_src ); // 2*I32 -> F64
1178       }
1179    }
1180 
1181    // Move to FPSCR
1182    addInstr(env, PPCInstr_FpLdFPSCR( fr_src, dfp_rm ));
1183 }
1184 
set_FPU_rounding_mode(ISelEnv * env,IRExpr * mode)1185 static void set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
1186 {
1187    _set_FPU_rounding_mode(env, mode, False);
1188 }
1189 
set_FPU_DFP_rounding_mode(ISelEnv * env,IRExpr * mode)1190 static void set_FPU_DFP_rounding_mode ( ISelEnv* env, IRExpr* mode )
1191 {
1192    _set_FPU_rounding_mode(env, mode, True);
1193 }
1194 
1195 
1196 /*---------------------------------------------------------*/
1197 /*--- ISEL: vector helpers                              ---*/
1198 /*---------------------------------------------------------*/
1199 
1200 /* Generate all-zeroes into a new vector register.
1201 */
generate_zeroes_V128(ISelEnv * env)1202 static HReg generate_zeroes_V128 ( ISelEnv* env )
1203 {
1204    HReg dst = newVRegV(env);
1205    addInstr(env, PPCInstr_AvBinary(Pav_XOR, dst, dst, dst));
1206    return dst;
1207 }
1208 
1209 /* Generate all-ones into a new vector register.
1210 */
generate_ones_V128(ISelEnv * env)1211 static HReg generate_ones_V128 ( ISelEnv* env )
1212 {
1213    HReg dst = newVRegV(env);
1214    PPCVI5s * src = PPCVI5s_Imm(-1);
1215    addInstr(env, PPCInstr_AvSplat(8, dst, src));
1216    return dst;
1217 }
1218 
1219 
1220 /*
1221   Generates code for AvSplat
1222   - takes in IRExpr* of type 8|16|32
1223     returns vector reg of duplicated lanes of input
1224   - uses AvSplat(imm) for imms up to simm6.
1225     otherwise must use store reg & load vector
1226 */
mk_AvDuplicateRI(ISelEnv * env,IRExpr * e)1227 static HReg mk_AvDuplicateRI( ISelEnv* env, IRExpr* e )
1228 {
1229    HReg   r_src;
1230    HReg   dst = newVRegV(env);
1231    PPCRI* ri  = iselWordExpr_RI(env, e);
1232    IRType ty  = typeOfIRExpr(env->type_env,e);
1233    UInt   sz  = (ty == Ity_I8) ? 8 : (ty == Ity_I16) ? 16 : 32;
1234    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
1235 
1236    /* special case: immediate */
1237    if (ri->tag == Pri_Imm) {
1238       Int simm32 = (Int)ri->Pri.Imm;
1239 
1240       /* figure out if it's do-able with imm splats. */
1241       if (simm32 >= -32 && simm32 <= 31) {
1242          Char simm6 = (Char)simm32;
1243          if (simm6 > 15) {           /* 16:31 inclusive */
1244             HReg v1 = newVRegV(env);
1245             HReg v2 = newVRegV(env);
1246             addInstr(env, PPCInstr_AvSplat(sz, v1, PPCVI5s_Imm(-16)));
1247             addInstr(env, PPCInstr_AvSplat(sz, v2, PPCVI5s_Imm(simm6-16)));
1248             addInstr(env,
1249                (sz== 8) ? PPCInstr_AvBin8x16(Pav_SUBU, dst, v2, v1) :
1250                (sz==16) ? PPCInstr_AvBin16x8(Pav_SUBU, dst, v2, v1)
1251                         : PPCInstr_AvBin32x4(Pav_SUBU, dst, v2, v1) );
1252             return dst;
1253          }
1254          if (simm6 < -16) {          /* -32:-17 inclusive */
1255             HReg v1 = newVRegV(env);
1256             HReg v2 = newVRegV(env);
1257             addInstr(env, PPCInstr_AvSplat(sz, v1, PPCVI5s_Imm(-16)));
1258             addInstr(env, PPCInstr_AvSplat(sz, v2, PPCVI5s_Imm(simm6+16)));
1259             addInstr(env,
1260                (sz== 8) ? PPCInstr_AvBin8x16(Pav_ADDU, dst, v2, v1) :
1261                (sz==16) ? PPCInstr_AvBin16x8(Pav_ADDU, dst, v2, v1)
1262                         : PPCInstr_AvBin32x4(Pav_ADDU, dst, v2, v1) );
1263             return dst;
1264          }
1265          /* simplest form:              -16:15 inclusive */
1266          addInstr(env, PPCInstr_AvSplat(sz, dst, PPCVI5s_Imm(simm6)));
1267          return dst;
1268       }
1269 
1270       /* no luck; use the Slow way. */
1271       r_src = newVRegI(env);
1272       addInstr(env, PPCInstr_LI(r_src, (Long)simm32, env->mode64));
1273    }
1274    else {
1275       r_src = ri->Pri.Reg;
1276    }
1277 
1278    /* default case: store r_src in lowest lane of 16-aligned mem,
1279       load vector, splat lowest lane to dst */
1280    {
1281       /* CAB: Maybe faster to store r_src multiple times (sz dependent),
1282               and simply load the vector? */
1283       HReg r_aligned16;
1284       HReg v_src = newVRegV(env);
1285       PPCAMode *am_off12;
1286 
1287       sub_from_sp( env, 32 );     // Move SP down
1288       /* Get a 16-aligned address within our stack space */
1289       r_aligned16 = get_sp_aligned16( env );
1290       am_off12 = PPCAMode_IR( 12, r_aligned16 );
1291 
1292       /* Store r_src in low word of 16-aligned mem */
1293       addInstr(env, PPCInstr_Store( 4, am_off12, r_src, env->mode64 ));
1294 
1295       /* Load src to vector[low lane] */
1296       addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, v_src, am_off12 ) );
1297       add_to_sp( env, 32 );       // Reset SP
1298 
1299       /* Finally, splat v_src[low_lane] to dst */
1300       addInstr(env, PPCInstr_AvSplat(sz, dst, PPCVI5s_Reg(v_src)));
1301       return dst;
1302    }
1303 }
1304 
1305 
1306 /* for each lane of vSrc: lane == nan ? laneX = all 1's : all 0's */
isNan(ISelEnv * env,HReg vSrc)1307 static HReg isNan ( ISelEnv* env, HReg vSrc )
1308 {
1309    HReg zeros, msk_exp, msk_mnt, expt, mnts, vIsNan;
1310 
1311    vassert(hregClass(vSrc) == HRcVec128);
1312 
1313    zeros   = mk_AvDuplicateRI(env, mkU32(0));
1314    msk_exp = mk_AvDuplicateRI(env, mkU32(0x7F800000));
1315    msk_mnt = mk_AvDuplicateRI(env, mkU32(0x7FFFFF));
1316    expt    = newVRegV(env);
1317    mnts    = newVRegV(env);
1318    vIsNan  = newVRegV(env);
1319 
1320    /* 32bit float => sign(1) | exponent(8) | mantissa(23)
1321       nan => exponent all ones, mantissa > 0 */
1322 
1323    addInstr(env, PPCInstr_AvBinary(Pav_AND, expt, vSrc, msk_exp));
1324    addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, expt, expt, msk_exp));
1325    addInstr(env, PPCInstr_AvBinary(Pav_AND, mnts, vSrc, msk_mnt));
1326    addInstr(env, PPCInstr_AvBin32x4(Pav_CMPGTU, mnts, mnts, zeros));
1327    addInstr(env, PPCInstr_AvBinary(Pav_AND, vIsNan, expt, mnts));
1328    return vIsNan;
1329 }
1330 
1331 
1332 /*---------------------------------------------------------*/
1333 /*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
1334 /*---------------------------------------------------------*/
1335 
1336 /* Select insns for an integer-typed expression, and add them to the
1337    code list.  Return a reg holding the result.  This reg will be a
1338    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
1339    want to modify it, ask for a new vreg, copy it in there, and modify
1340    the copy.  The register allocator will do its best to map both
1341    vregs to the same real register, so the copies will often disappear
1342    later in the game.
1343 
1344    This should handle expressions of 64, 32, 16 and 8-bit type.
1345    All results are returned in a (mode64 ? 64bit : 32bit) register.
1346    For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
1347    are arbitrary, so you should mask or sign extend partial values
1348    if necessary.
1349 */
1350 
iselWordExpr_R(ISelEnv * env,IRExpr * e)1351 static HReg iselWordExpr_R ( ISelEnv* env, IRExpr* e )
1352 {
1353    HReg r = iselWordExpr_R_wrk(env, e);
1354    /* sanity checks ... */
1355 #  if 0
1356    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
1357 #  endif
1358 
1359    vassert(hregClass(r) == HRcGPR(env->mode64));
1360    vassert(hregIsVirtual(r));
1361    return r;
1362 }
1363 
1364 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_R_wrk(ISelEnv * env,IRExpr * e)1365 static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e )
1366 {
1367    Bool mode64 = env->mode64;
1368    MatchInfo mi;
1369    DECLARE_PATTERN(p_32to1_then_1Uto8);
1370 
1371    IRType ty = typeOfIRExpr(env->type_env,e);
1372    vassert(ty == Ity_I8 || ty == Ity_I16 ||
1373            ty == Ity_I32 || ((ty == Ity_I64) && mode64));
1374 
1375    switch (e->tag) {
1376 
1377    /* --------- TEMP --------- */
1378    case Iex_RdTmp:
1379       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
1380 
1381    /* --------- LOAD --------- */
1382    case Iex_Load: {
1383       HReg      r_dst;
1384       PPCAMode* am_addr;
1385       if (e->Iex.Load.end != Iend_BE)
1386          goto irreducible;
1387       r_dst   = newVRegI(env);
1388       am_addr = iselWordExpr_AMode( env, e->Iex.Load.addr, ty/*of xfer*/ );
1389       addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
1390                                    r_dst, am_addr, mode64 ));
1391       return r_dst;
1392       /*NOTREACHED*/
1393    }
1394 
1395    /* --------- BINARY OP --------- */
1396    case Iex_Binop: {
1397       PPCAluOp  aluOp;
1398       PPCShftOp shftOp;
1399 
1400       /* Is it an addition or logical style op? */
1401       switch (e->Iex.Binop.op) {
1402       case Iop_Add8: case Iop_Add16: case Iop_Add32: case Iop_Add64:
1403          aluOp = Palu_ADD; break;
1404       case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: case Iop_Sub64:
1405          aluOp = Palu_SUB; break;
1406       case Iop_And8: case Iop_And16: case Iop_And32: case Iop_And64:
1407          aluOp = Palu_AND; break;
1408       case Iop_Or8:  case Iop_Or16:  case Iop_Or32:  case Iop_Or64:
1409          aluOp = Palu_OR; break;
1410       case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: case Iop_Xor64:
1411          aluOp = Palu_XOR; break;
1412       default:
1413          aluOp = Palu_INVALID; break;
1414       }
1415       /* For commutative ops we assume any literal
1416          values are on the second operand. */
1417       if (aluOp != Palu_INVALID) {
1418          HReg   r_dst   = newVRegI(env);
1419          HReg   r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1420          PPCRH* ri_srcR = NULL;
1421          /* get right arg into an RH, in the appropriate way */
1422          switch (aluOp) {
1423          case Palu_ADD: case Palu_SUB:
1424             ri_srcR = iselWordExpr_RH(env, True/*signed*/,
1425                                       e->Iex.Binop.arg2);
1426             break;
1427          case Palu_AND: case Palu_OR: case Palu_XOR:
1428             ri_srcR = iselWordExpr_RH(env, False/*signed*/,
1429                                       e->Iex.Binop.arg2);
1430             break;
1431          default:
1432             vpanic("iselWordExpr_R_wrk-aluOp-arg2");
1433          }
1434          addInstr(env, PPCInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
1435          return r_dst;
1436       }
1437 
1438       /* a shift? */
1439       switch (e->Iex.Binop.op) {
1440       case Iop_Shl8: case Iop_Shl16: case Iop_Shl32: case Iop_Shl64:
1441          shftOp = Pshft_SHL; break;
1442       case Iop_Shr8: case Iop_Shr16: case Iop_Shr32: case Iop_Shr64:
1443          shftOp = Pshft_SHR; break;
1444       case Iop_Sar8: case Iop_Sar16: case Iop_Sar32: case Iop_Sar64:
1445          shftOp = Pshft_SAR; break;
1446       default:
1447          shftOp = Pshft_INVALID; break;
1448       }
1449       /* we assume any literal values are on the second operand. */
1450       if (shftOp != Pshft_INVALID) {
1451          HReg   r_dst   = newVRegI(env);
1452          HReg   r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1453          PPCRH* ri_srcR = NULL;
1454          /* get right arg into an RH, in the appropriate way */
1455          switch (shftOp) {
1456          case Pshft_SHL: case Pshft_SHR: case Pshft_SAR:
1457             if (!mode64)
1458                ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2);
1459             else
1460                ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
1461             break;
1462          default:
1463             vpanic("iselIntExpr_R_wrk-shftOp-arg2");
1464          }
1465          /* widen the left arg if needed */
1466          if (shftOp == Pshft_SHR || shftOp == Pshft_SAR) {
1467             if (ty == Ity_I8 || ty == Ity_I16) {
1468                PPCRH* amt = PPCRH_Imm(False,
1469                                       toUShort(ty == Ity_I8 ? 24 : 16));
1470                HReg   tmp = newVRegI(env);
1471                addInstr(env, PPCInstr_Shft(Pshft_SHL,
1472                                            True/*32bit shift*/,
1473                                            tmp, r_srcL, amt));
1474                addInstr(env, PPCInstr_Shft(shftOp,
1475                                            True/*32bit shift*/,
1476                                            tmp, tmp,    amt));
1477                r_srcL = tmp;
1478                vassert(0); /* AWAITING TEST CASE */
1479             }
1480          }
1481          /* Only 64 expressions need 64bit shifts,
1482             32bit shifts are fine for all others */
1483          if (ty == Ity_I64) {
1484             vassert(mode64);
1485             addInstr(env, PPCInstr_Shft(shftOp, False/*64bit shift*/,
1486                                         r_dst, r_srcL, ri_srcR));
1487          } else {
1488             addInstr(env, PPCInstr_Shft(shftOp, True/*32bit shift*/,
1489                                         r_dst, r_srcL, ri_srcR));
1490          }
1491          return r_dst;
1492       }
1493 
1494       /* How about a div? */
1495       if (e->Iex.Binop.op == Iop_DivS32 ||
1496           e->Iex.Binop.op == Iop_DivU32 ||
1497           e->Iex.Binop.op == Iop_DivS32E ||
1498           e->Iex.Binop.op == Iop_DivU32E) {
1499          Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS32) || (e->Iex.Binop.op == Iop_DivS32E));
1500          HReg r_dst  = newVRegI(env);
1501          HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1502          HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1503          addInstr( env,
1504                       PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivU32E )
1505                                              || ( e->Iex.Binop.op == Iop_DivS32E ) ) ? True
1506                                                                                      : False,
1507                                     syned,
1508                                     True/*32bit div*/,
1509                                     r_dst,
1510                                     r_srcL,
1511                                     r_srcR ) );
1512          return r_dst;
1513       }
1514       if (e->Iex.Binop.op == Iop_DivS64 ||
1515           e->Iex.Binop.op == Iop_DivU64 || e->Iex.Binop.op == Iop_DivS64E
1516           || e->Iex.Binop.op == Iop_DivU64E ) {
1517          Bool syned  = toBool((e->Iex.Binop.op == Iop_DivS64) ||(e->Iex.Binop.op == Iop_DivS64E));
1518          HReg r_dst  = newVRegI(env);
1519          HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1520          HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1521          vassert(mode64);
1522          addInstr( env,
1523                       PPCInstr_Div( ( ( e->Iex.Binop.op == Iop_DivS64E )
1524                                              || ( e->Iex.Binop.op
1525                                                       == Iop_DivU64E ) ) ? True
1526                                                                          : False,
1527                                     syned,
1528                                     False/*64bit div*/,
1529                                     r_dst,
1530                                     r_srcL,
1531                                     r_srcR ) );
1532          return r_dst;
1533       }
1534 
1535       /* No? Anyone for a mul? */
1536       if (e->Iex.Binop.op == Iop_Mul32
1537           || e->Iex.Binop.op == Iop_Mul64) {
1538          Bool syned       = False;
1539          Bool sz32        = (e->Iex.Binop.op != Iop_Mul64);
1540          HReg r_dst       = newVRegI(env);
1541          HReg r_srcL      = iselWordExpr_R(env, e->Iex.Binop.arg1);
1542          HReg r_srcR      = iselWordExpr_R(env, e->Iex.Binop.arg2);
1543          addInstr(env, PPCInstr_MulL(syned, False/*lo32*/, sz32,
1544                                      r_dst, r_srcL, r_srcR));
1545          return r_dst;
1546       }
1547 
1548       /* 32 x 32 -> 64 multiply */
1549       if (mode64
1550           && (e->Iex.Binop.op == Iop_MullU32
1551               || e->Iex.Binop.op == Iop_MullS32)) {
1552          HReg tLo    = newVRegI(env);
1553          HReg tHi    = newVRegI(env);
1554          HReg r_dst  = newVRegI(env);
1555          Bool syned  = toBool(e->Iex.Binop.op == Iop_MullS32);
1556          HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1557          HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1558          addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
1559                                      False/*lo32*/, True/*32bit mul*/,
1560                                      tLo, r_srcL, r_srcR));
1561          addInstr(env, PPCInstr_MulL(syned,
1562                                      True/*hi32*/, True/*32bit mul*/,
1563                                      tHi, r_srcL, r_srcR));
1564          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1565                                      r_dst, tHi, PPCRH_Imm(False,32)));
1566          addInstr(env, PPCInstr_Alu(Palu_OR,
1567                                     r_dst, r_dst, PPCRH_Reg(tLo)));
1568          return r_dst;
1569       }
1570 
1571       /* El-mutanto 3-way compare? */
1572       if (e->Iex.Binop.op == Iop_CmpORD32S
1573           || e->Iex.Binop.op == Iop_CmpORD32U) {
1574          Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD32S);
1575          HReg   dst   = newVRegI(env);
1576          HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1577          PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
1578          addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
1579                                     7/*cr*/, srcL, srcR));
1580          addInstr(env, PPCInstr_MfCR(dst));
1581          addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1582                                     PPCRH_Imm(False,7<<1)));
1583          return dst;
1584       }
1585 
1586       if (e->Iex.Binop.op == Iop_CmpORD64S
1587           || e->Iex.Binop.op == Iop_CmpORD64U) {
1588          Bool   syned = toBool(e->Iex.Binop.op == Iop_CmpORD64S);
1589          HReg   dst   = newVRegI(env);
1590          HReg   srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1591          PPCRH* srcR  = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
1592          vassert(mode64);
1593          addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
1594                                     7/*cr*/, srcL, srcR));
1595          addInstr(env, PPCInstr_MfCR(dst));
1596          addInstr(env, PPCInstr_Alu(Palu_AND, dst, dst,
1597                                     PPCRH_Imm(False,7<<1)));
1598          return dst;
1599       }
1600 
1601       if (e->Iex.Binop.op == Iop_Max32U) {
1602          HReg        r1   = iselWordExpr_R(env, e->Iex.Binop.arg1);
1603          HReg        r2   = iselWordExpr_R(env, e->Iex.Binop.arg2);
1604          HReg        rdst = newVRegI(env);
1605          PPCCondCode cc   = mk_PPCCondCode( Pct_TRUE, Pcf_7LT );
1606          addInstr(env, mk_iMOVds_RR(rdst, r1));
1607          addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
1608                                     7/*cr*/, rdst, PPCRH_Reg(r2)));
1609          addInstr(env, PPCInstr_CMov(cc, rdst, PPCRI_Reg(r2)));
1610          return rdst;
1611       }
1612 
1613       if (e->Iex.Binop.op == Iop_32HLto64) {
1614          HReg   r_Hi  = iselWordExpr_R(env, e->Iex.Binop.arg1);
1615          HReg   r_Lo  = iselWordExpr_R(env, e->Iex.Binop.arg2);
1616          HReg   r_Tmp = newVRegI(env);
1617          HReg   r_dst = newVRegI(env);
1618          HReg   msk   = newVRegI(env);
1619          vassert(mode64);
1620          /* r_dst = OR( r_Hi<<32, r_Lo ) */
1621          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1622                                      r_dst, r_Hi, PPCRH_Imm(False,32)));
1623          addInstr(env, PPCInstr_LI(msk, 0xFFFFFFFF, mode64));
1624          addInstr(env, PPCInstr_Alu( Palu_AND, r_Tmp, r_Lo,
1625                                      PPCRH_Reg(msk) ));
1626          addInstr(env, PPCInstr_Alu( Palu_OR, r_dst, r_dst,
1627                                      PPCRH_Reg(r_Tmp) ));
1628          return r_dst;
1629       }
1630 
1631       if ((e->Iex.Binop.op == Iop_CmpF64) ||
1632           (e->Iex.Binop.op == Iop_CmpD64) ||
1633           (e->Iex.Binop.op == Iop_CmpD128)) {
1634          HReg fr_srcL;
1635          HReg fr_srcL_lo;
1636          HReg fr_srcR;
1637          HReg fr_srcR_lo;
1638 
1639          HReg r_ccPPC   = newVRegI(env);
1640          HReg r_ccIR    = newVRegI(env);
1641          HReg r_ccIR_b0 = newVRegI(env);
1642          HReg r_ccIR_b2 = newVRegI(env);
1643          HReg r_ccIR_b6 = newVRegI(env);
1644 
1645          if (e->Iex.Binop.op == Iop_CmpF64) {
1646             fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
1647             fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
1648             addInstr(env, PPCInstr_FpCmp(r_ccPPC, fr_srcL, fr_srcR));
1649 
1650          } else if (e->Iex.Binop.op == Iop_CmpD64) {
1651             fr_srcL = iselDfp64Expr(env, e->Iex.Binop.arg1);
1652             fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2);
1653             addInstr(env, PPCInstr_Dfp64Cmp(r_ccPPC, fr_srcL, fr_srcR));
1654 
1655          } else {    //  e->Iex.Binop.op == Iop_CmpD128
1656             iselDfp128Expr(&fr_srcL, &fr_srcL_lo, env, e->Iex.Binop.arg1);
1657             iselDfp128Expr(&fr_srcR, &fr_srcR_lo, env, e->Iex.Binop.arg2);
1658             addInstr(env, PPCInstr_Dfp128Cmp(r_ccPPC, fr_srcL, fr_srcL_lo,
1659                                              fr_srcR, fr_srcR_lo));
1660          }
1661 
1662          /* Map compare result from PPC to IR,
1663             conforming to CmpF64 definition. */
1664          /*
1665            FP cmp result | PPC | IR
1666            --------------------------
1667            UN            | 0x1 | 0x45
1668            EQ            | 0x2 | 0x40
1669            GT            | 0x4 | 0x00
1670            LT            | 0x8 | 0x01
1671          */
1672 
1673          // r_ccIR_b0 = r_ccPPC[0] | r_ccPPC[3]
1674          addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1675                                      r_ccIR_b0, r_ccPPC,
1676                                      PPCRH_Imm(False,0x3)));
1677          addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b0,
1678                                     r_ccPPC,   PPCRH_Reg(r_ccIR_b0)));
1679          addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b0,
1680                                     r_ccIR_b0, PPCRH_Imm(False,0x1)));
1681 
1682          // r_ccIR_b2 = r_ccPPC[0]
1683          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1684                                      r_ccIR_b2, r_ccPPC,
1685                                      PPCRH_Imm(False,0x2)));
1686          addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b2,
1687                                     r_ccIR_b2, PPCRH_Imm(False,0x4)));
1688 
1689          // r_ccIR_b6 = r_ccPPC[0] | r_ccPPC[1]
1690          addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1691                                      r_ccIR_b6, r_ccPPC,
1692                                      PPCRH_Imm(False,0x1)));
1693          addInstr(env, PPCInstr_Alu(Palu_OR,  r_ccIR_b6,
1694                                     r_ccPPC, PPCRH_Reg(r_ccIR_b6)));
1695          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1696                                      r_ccIR_b6, r_ccIR_b6,
1697                                      PPCRH_Imm(False,0x6)));
1698          addInstr(env, PPCInstr_Alu(Palu_AND, r_ccIR_b6,
1699                                     r_ccIR_b6, PPCRH_Imm(False,0x40)));
1700 
1701          // r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6
1702          addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1703                                     r_ccIR_b0, PPCRH_Reg(r_ccIR_b2)));
1704          addInstr(env, PPCInstr_Alu(Palu_OR, r_ccIR,
1705                                     r_ccIR,    PPCRH_Reg(r_ccIR_b6)));
1706          return r_ccIR;
1707       }
1708 
1709       if ( e->Iex.Binop.op == Iop_F64toI32S ||
1710                e->Iex.Binop.op == Iop_F64toI32U ) {
1711          /* This works in both mode64 and mode32. */
1712          HReg      r1      = StackFramePtr(env->mode64);
1713          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1714          HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2);
1715          HReg      ftmp    = newVRegF(env);
1716          HReg      idst    = newVRegI(env);
1717 
1718          /* Set host rounding mode */
1719          set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
1720 
1721          sub_from_sp( env, 16 );
1722          addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/,
1723                                        e->Iex.Binop.op == Iop_F64toI32S ? True/*syned*/
1724                                                                      : False,
1725                                        True/*flt64*/,
1726                                        ftmp, fsrc));
1727          addInstr(env, PPCInstr_FpSTFIW(r1, ftmp));
1728          addInstr(env, PPCInstr_Load(4, idst, zero_r1, mode64));
1729 
1730          /* in 64-bit mode we need to sign-widen idst. */
1731          if (mode64)
1732             addInstr(env, PPCInstr_Unary(Pun_EXTSW, idst, idst));
1733 
1734          add_to_sp( env, 16 );
1735 
1736          ///* Restore default FPU rounding. */
1737          //set_FPU_rounding_default( env );
1738          return idst;
1739       }
1740 
1741       if (e->Iex.Binop.op == Iop_F64toI64S || e->Iex.Binop.op == Iop_F64toI64U ) {
1742          if (mode64) {
1743             HReg      r1      = StackFramePtr(env->mode64);
1744             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1745             HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2);
1746             HReg      idst    = newVRegI(env);
1747             HReg      ftmp    = newVRegF(env);
1748 
1749             /* Set host rounding mode */
1750             set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
1751 
1752             sub_from_sp( env, 16 );
1753             addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
1754                                           ( e->Iex.Binop.op == Iop_F64toI64S ) ? True
1755                                                                             : False,
1756                                           True, ftmp, fsrc));
1757             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1758             addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
1759             add_to_sp( env, 16 );
1760 
1761             ///* Restore default FPU rounding. */
1762             //set_FPU_rounding_default( env );
1763             return idst;
1764          }
1765       }
1766 
1767       if (e->Iex.Binop.op == Iop_D64toI64S ) {
1768          HReg      r1      = StackFramePtr(env->mode64);
1769          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
1770          HReg      fr_src  = iselDfp64Expr(env, e->Iex.Binop.arg2);
1771          HReg      idst    = newVRegI(env);
1772          HReg      ftmp    = newVRegF(env);
1773 
1774          /* Set host rounding mode */
1775          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
1776          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTFIX, ftmp, fr_src));
1777          sub_from_sp( env, 16 );
1778          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1779          addInstr(env, PPCInstr_Load(8, idst, zero_r1, mode64));
1780 
1781          add_to_sp( env, 16 );
1782 
1783          ///* Restore default FPU rounding. */
1784          //set_FPU_rounding_default( env );
1785          return idst;
1786       }
1787 
1788       if (e->Iex.Binop.op == Iop_D128toI64S ) {
1789          PPCFpOp fpop = Pfp_DCTFIXQ;
1790          HReg r_srcHi = newVRegF(env);
1791          HReg r_srcLo = newVRegF(env);
1792          HReg idst    = newVRegI(env);
1793          HReg ftmp    = newVRegF(env);
1794          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
1795 
1796          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
1797          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
1798          addInstr(env, PPCInstr_DfpD128toD64(fpop, ftmp, r_srcHi, r_srcLo));
1799 
1800          // put the D64 result into an integer register
1801          sub_from_sp( env, 16 );
1802          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
1803          addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/));
1804          add_to_sp( env, 16 );
1805          return idst;
1806       }
1807       break;
1808    }
1809 
1810    /* --------- UNARY OP --------- */
1811    case Iex_Unop: {
1812       IROp op_unop = e->Iex.Unop.op;
1813 
1814       /* 1Uto8(32to1(expr32)) */
1815       DEFINE_PATTERN(p_32to1_then_1Uto8,
1816                      unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
1817       if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
1818          IRExpr* expr32 = mi.bindee[0];
1819          HReg r_dst = newVRegI(env);
1820          HReg r_src = iselWordExpr_R(env, expr32);
1821          addInstr(env, PPCInstr_Alu(Palu_AND, r_dst,
1822                                     r_src, PPCRH_Imm(False,1)));
1823          return r_dst;
1824       }
1825 
1826       /* 16Uto32(LDbe:I16(expr32)) */
1827       {
1828          DECLARE_PATTERN(p_LDbe16_then_16Uto32);
1829          DEFINE_PATTERN(p_LDbe16_then_16Uto32,
1830                         unop(Iop_16Uto32,
1831                              IRExpr_Load(Iend_BE,Ity_I16,bind(0))) );
1832          if (matchIRExpr(&mi,p_LDbe16_then_16Uto32,e)) {
1833             HReg r_dst = newVRegI(env);
1834             PPCAMode* amode
1835                = iselWordExpr_AMode( env, mi.bindee[0], Ity_I16/*xfer*/ );
1836             addInstr(env, PPCInstr_Load(2,r_dst,amode, mode64));
1837             return r_dst;
1838          }
1839       }
1840 
1841       switch (op_unop) {
1842       case Iop_8Uto16:
1843       case Iop_8Uto32:
1844       case Iop_8Uto64:
1845       case Iop_16Uto32:
1846       case Iop_16Uto64: {
1847          HReg   r_dst = newVRegI(env);
1848          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1849          UShort mask  = toUShort(op_unop==Iop_16Uto64 ? 0xFFFF :
1850                                  op_unop==Iop_16Uto32 ? 0xFFFF : 0xFF);
1851          addInstr(env, PPCInstr_Alu(Palu_AND,r_dst,r_src,
1852                                     PPCRH_Imm(False,mask)));
1853          return r_dst;
1854       }
1855       case Iop_32Uto64: {
1856          HReg r_dst = newVRegI(env);
1857          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1858          vassert(mode64);
1859          addInstr(env,
1860                   PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1861                                 r_dst, r_src, PPCRH_Imm(False,32)));
1862          addInstr(env,
1863                   PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1864                                 r_dst, r_dst, PPCRH_Imm(False,32)));
1865          return r_dst;
1866       }
1867       case Iop_8Sto16:
1868       case Iop_8Sto32:
1869       case Iop_16Sto32: {
1870          HReg   r_dst = newVRegI(env);
1871          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1872          UShort amt   = toUShort(op_unop==Iop_16Sto32 ? 16 : 24);
1873          addInstr(env,
1874                   PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1875                                 r_dst, r_src, PPCRH_Imm(False,amt)));
1876          addInstr(env,
1877                   PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1878                                 r_dst, r_dst, PPCRH_Imm(False,amt)));
1879          return r_dst;
1880       }
1881       case Iop_8Sto64:
1882       case Iop_16Sto64: {
1883          HReg   r_dst = newVRegI(env);
1884          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1885          UShort amt   = toUShort(op_unop==Iop_8Sto64  ? 56 : 48);
1886          vassert(mode64);
1887          addInstr(env,
1888                   PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
1889                                 r_dst, r_src, PPCRH_Imm(False,amt)));
1890          addInstr(env,
1891                   PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
1892                                 r_dst, r_dst, PPCRH_Imm(False,amt)));
1893          return r_dst;
1894       }
1895       case Iop_32Sto64: {
1896          HReg   r_dst = newVRegI(env);
1897          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1898 	 vassert(mode64);
1899          /* According to the IBM docs, in 64 bit mode, srawi r,r,0
1900             sign extends the lower 32 bits into the upper 32 bits. */
1901          addInstr(env,
1902                   PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1903                                 r_dst, r_src, PPCRH_Imm(False,0)));
1904          return r_dst;
1905       }
1906       case Iop_Not8:
1907       case Iop_Not16:
1908       case Iop_Not32:
1909       case Iop_Not64: {
1910          if (op_unop == Iop_Not64) vassert(mode64);
1911          HReg r_dst = newVRegI(env);
1912          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1913          addInstr(env, PPCInstr_Unary(Pun_NOT,r_dst,r_src));
1914          return r_dst;
1915       }
1916       case Iop_64HIto32: {
1917          if (!mode64) {
1918             HReg rHi, rLo;
1919             iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1920             return rHi; /* and abandon rLo .. poor wee thing :-) */
1921          } else {
1922             HReg   r_dst = newVRegI(env);
1923             HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1924             addInstr(env,
1925                      PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/,
1926                                    r_dst, r_src, PPCRH_Imm(False,32)));
1927             return r_dst;
1928          }
1929       }
1930       case Iop_64to32: {
1931          if (!mode64) {
1932             HReg rHi, rLo;
1933             iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1934             return rLo; /* similar stupid comment to the above ... */
1935          } else {
1936             /* This is a no-op. */
1937             return iselWordExpr_R(env, e->Iex.Unop.arg);
1938          }
1939       }
1940       case Iop_64to16: {
1941          if (mode64) { /* This is a no-op. */
1942             return iselWordExpr_R(env, e->Iex.Unop.arg);
1943          }
1944          break; /* evidently not used in 32-bit mode */
1945       }
1946       case Iop_16HIto8:
1947       case Iop_32HIto16: {
1948          HReg   r_dst = newVRegI(env);
1949          HReg   r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1950          UShort shift = toUShort(op_unop == Iop_16HIto8 ? 8 : 16);
1951          addInstr(env,
1952                   PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/,
1953                                 r_dst, r_src, PPCRH_Imm(False,shift)));
1954          return r_dst;
1955       }
1956       case Iop_128HIto64:
1957          if (mode64) {
1958             HReg rHi, rLo;
1959             iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1960             return rHi; /* and abandon rLo .. poor wee thing :-) */
1961          }
1962          break;
1963       case Iop_128to64:
1964          if (mode64) {
1965             HReg rHi, rLo;
1966             iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1967             return rLo; /* similar stupid comment to the above ... */
1968          }
1969          break;
1970       case Iop_1Uto64:
1971       case Iop_1Uto32:
1972       case Iop_1Uto8:
1973          if ((op_unop != Iop_1Uto64) || mode64) {
1974             HReg        r_dst = newVRegI(env);
1975             PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg);
1976             addInstr(env, PPCInstr_Set(cond,r_dst));
1977             return r_dst;
1978          }
1979          break;
1980       case Iop_1Sto8:
1981       case Iop_1Sto16:
1982       case Iop_1Sto32: {
1983          /* could do better than this, but for now ... */
1984          HReg        r_dst = newVRegI(env);
1985          PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg);
1986          addInstr(env, PPCInstr_Set(cond,r_dst));
1987          addInstr(env,
1988                   PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
1989                                 r_dst, r_dst, PPCRH_Imm(False,31)));
1990          addInstr(env,
1991                   PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
1992                                 r_dst, r_dst, PPCRH_Imm(False,31)));
1993          return r_dst;
1994       }
1995       case Iop_1Sto64:
1996          if (mode64) {
1997             /* could do better than this, but for now ... */
1998             HReg        r_dst = newVRegI(env);
1999             PPCCondCode cond  = iselCondCode(env, e->Iex.Unop.arg);
2000             addInstr(env, PPCInstr_Set(cond,r_dst));
2001             addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
2002                                         r_dst, r_dst, PPCRH_Imm(False,63)));
2003             addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
2004                                         r_dst, r_dst, PPCRH_Imm(False,63)));
2005             return r_dst;
2006          }
2007          break;
2008       case Iop_Clz32:
2009       case Iop_Clz64: {
2010          HReg r_src, r_dst;
2011          PPCUnaryOp op_clz = (op_unop == Iop_Clz32) ? Pun_CLZ32 :
2012                                                       Pun_CLZ64;
2013          if (op_unop == Iop_Clz64 && !mode64)
2014             goto irreducible;
2015          /* Count leading zeroes. */
2016          r_dst = newVRegI(env);
2017          r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2018          addInstr(env, PPCInstr_Unary(op_clz,r_dst,r_src));
2019          return r_dst;
2020       }
2021 
2022       case Iop_Left8:
2023       case Iop_Left16:
2024       case Iop_Left32:
2025       case Iop_Left64: {
2026          HReg r_src, r_dst;
2027          if (op_unop == Iop_Left64 && !mode64)
2028             goto irreducible;
2029          r_dst = newVRegI(env);
2030          r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2031          addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
2032          addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
2033          return r_dst;
2034       }
2035 
2036       case Iop_CmpwNEZ32: {
2037          HReg r_dst = newVRegI(env);
2038          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2039          addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
2040          addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
2041          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
2042                                      r_dst, r_dst, PPCRH_Imm(False, 31)));
2043          return r_dst;
2044       }
2045 
2046       case Iop_CmpwNEZ64: {
2047          HReg r_dst = newVRegI(env);
2048          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2049          if (!mode64) goto irreducible;
2050          addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src));
2051          addInstr(env, PPCInstr_Alu(Palu_OR, r_dst, r_dst, PPCRH_Reg(r_src)));
2052          addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/,
2053                                      r_dst, r_dst, PPCRH_Imm(False, 63)));
2054          return r_dst;
2055       }
2056 
2057       case Iop_V128to32: {
2058          HReg        r_aligned16;
2059          HReg        dst  = newVRegI(env);
2060          HReg        vec  = iselVecExpr(env, e->Iex.Unop.arg);
2061          PPCAMode *am_off0, *am_off12;
2062          sub_from_sp( env, 32 );     // Move SP down 32 bytes
2063 
2064          // get a quadword aligned address within our stack space
2065          r_aligned16 = get_sp_aligned16( env );
2066          am_off0  = PPCAMode_IR( 0, r_aligned16 );
2067          am_off12 = PPCAMode_IR( 12,r_aligned16 );
2068 
2069          // store vec, load low word to dst
2070          addInstr(env,
2071                   PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
2072          addInstr(env,
2073                   PPCInstr_Load( 4, dst, am_off12, mode64 ));
2074 
2075          add_to_sp( env, 32 );       // Reset SP
2076          return dst;
2077       }
2078 
2079       case Iop_V128to64:
2080       case Iop_V128HIto64:
2081          if (mode64) {
2082             HReg     r_aligned16;
2083             HReg     dst = newVRegI(env);
2084             HReg     vec = iselVecExpr(env, e->Iex.Unop.arg);
2085             PPCAMode *am_off0, *am_off8;
2086             sub_from_sp( env, 32 );     // Move SP down 32 bytes
2087 
2088             // get a quadword aligned address within our stack space
2089             r_aligned16 = get_sp_aligned16( env );
2090             am_off0 = PPCAMode_IR( 0, r_aligned16 );
2091             am_off8 = PPCAMode_IR( 8 ,r_aligned16 );
2092 
2093             // store vec, load low word (+8) or high (+0) to dst
2094             addInstr(env,
2095                      PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
2096             addInstr(env,
2097                      PPCInstr_Load(
2098                         8, dst,
2099                         op_unop == Iop_V128HIto64 ? am_off0 : am_off8,
2100                         mode64 ));
2101 
2102             add_to_sp( env, 32 );       // Reset SP
2103             return dst;
2104          }
2105          break;
2106       case Iop_16to8:
2107       case Iop_32to8:
2108       case Iop_32to16:
2109       case Iop_64to8:
2110          /* These are no-ops. */
2111          return iselWordExpr_R(env, e->Iex.Unop.arg);
2112 
2113       /* ReinterpF64asI64(e) */
2114       /* Given an IEEE754 double, produce an I64 with the same bit
2115          pattern. */
2116       case Iop_ReinterpF64asI64:
2117          if (mode64) {
2118             PPCAMode *am_addr;
2119             HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
2120             HReg r_dst  = newVRegI(env);
2121 
2122             sub_from_sp( env, 16 );     // Move SP down 16 bytes
2123             am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
2124 
2125             // store as F64
2126             addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
2127                                            fr_src, am_addr ));
2128             // load as Ity_I64
2129             addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
2130 
2131             add_to_sp( env, 16 );       // Reset SP
2132             return r_dst;
2133          }
2134          break;
2135 
2136       /* ReinterpF32asI32(e) */
2137       /* Given an IEEE754 float, produce an I32 with the same bit
2138          pattern. */
2139       case Iop_ReinterpF32asI32: {
2140          /* I believe this generates correct code for both 32- and
2141             64-bit hosts. */
2142          PPCAMode *am_addr;
2143          HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
2144          HReg r_dst  = newVRegI(env);
2145 
2146          sub_from_sp( env, 16 );     // Move SP down 16 bytes
2147          am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
2148 
2149          // store as F32
2150          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
2151                                         fr_src, am_addr ));
2152          // load as Ity_I32
2153          addInstr(env, PPCInstr_Load( 4, r_dst, am_addr, mode64 ));
2154 
2155          add_to_sp( env, 16 );       // Reset SP
2156          return r_dst;
2157       }
2158       break;
2159 
2160       case Iop_ReinterpD64asI64:
2161          if (mode64) {
2162             PPCAMode *am_addr;
2163             HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
2164             HReg r_dst  = newVRegI(env);
2165 
2166             sub_from_sp( env, 16 );     // Move SP down 16 bytes
2167             am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) );
2168 
2169             // store as D64
2170             addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
2171                                            fr_src, am_addr ));
2172             // load as Ity_I64
2173             addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 ));
2174             add_to_sp( env, 16 );       // Reset SP
2175             return r_dst;
2176          }
2177          break;
2178 
2179       case Iop_BCDtoDPB: {
2180          /* the following is only valid in 64 bit mode */
2181          if (!mode64) break;
2182 
2183          PPCCondCode cc;
2184          UInt        argiregs;
2185          HReg        argregs[1];
2186          HReg        r_dst  = newVRegI(env);
2187          Int         argreg;
2188          HWord*      fdescr;
2189 
2190          argiregs = 0;
2191          argreg = 0;
2192          argregs[0] = hregPPC_GPR3(mode64);
2193 
2194          argiregs |= (1 << (argreg+3));
2195          addInstr(env, mk_iMOVds_RR( argregs[argreg++],
2196                                      iselWordExpr_R(env, e->Iex.Unop.arg) ) );
2197 
2198          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
2199 
2200          fdescr = (HWord*)h_calc_BCDtoDPB;
2201          addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]),
2202                                       argiregs, mk_RetLoc_simple(RLPri_Int)) );
2203 
2204          addInstr(env, mk_iMOVds_RR(r_dst, argregs[0]));
2205          return r_dst;
2206       }
2207 
2208       case Iop_DPBtoBCD: {
2209          /* the following is only valid in 64 bit mode */
2210          if (!mode64) break;
2211 
2212          PPCCondCode cc;
2213          UInt        argiregs;
2214          HReg        argregs[1];
2215          HReg        r_dst  = newVRegI(env);
2216          Int         argreg;
2217          HWord*      fdescr;
2218 
2219          argiregs = 0;
2220          argreg = 0;
2221          argregs[0] = hregPPC_GPR3(mode64);
2222 
2223          argiregs |= (1 << (argreg+3));
2224          addInstr(env, mk_iMOVds_RR( argregs[argreg++],
2225                                      iselWordExpr_R(env, e->Iex.Unop.arg) ) );
2226 
2227          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
2228 
2229          fdescr = (HWord*)h_calc_DPBtoBCD;
2230          addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]),
2231                                       argiregs, mk_RetLoc_simple(RLPri_Int) ) );
2232 
2233          addInstr(env, mk_iMOVds_RR(r_dst, argregs[0]));
2234          return r_dst;
2235       }
2236 
2237       default:
2238          break;
2239       }
2240 
2241      switch (e->Iex.Unop.op) {
2242         case Iop_ExtractExpD64: {
2243 
2244             HReg fr_dst = newVRegI(env);
2245             HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
2246             HReg tmp    = newVRegF(env);
2247             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
2248             addInstr(env, PPCInstr_Dfp64Unary(Pfp_DXEX, tmp, fr_src));
2249 
2250             // put the D64 result into a integer register
2251             sub_from_sp( env, 16 );
2252             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
2253             addInstr(env, PPCInstr_Load(8, fr_dst, zero_r1, env->mode64));
2254             add_to_sp( env, 16 );
2255             return fr_dst;
2256          }
2257          case Iop_ExtractExpD128: {
2258             HReg fr_dst = newVRegI(env);
2259             HReg r_srcHi;
2260             HReg r_srcLo;
2261             HReg tmp    = newVRegF(env);
2262             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
2263 
2264             iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
2265             addInstr(env, PPCInstr_ExtractExpD128(Pfp_DXEXQ, tmp,
2266                                                   r_srcHi, r_srcLo));
2267 
2268             sub_from_sp( env, 16 );
2269             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
2270             addInstr(env, PPCInstr_Load(8, fr_dst, zero_r1, env->mode64));
2271             add_to_sp( env, 16 );
2272             return fr_dst;
2273          }
2274          default:
2275             break;
2276       }
2277 
2278       break;
2279    }
2280 
2281    /* --------- GET --------- */
2282    case Iex_Get: {
2283       if (ty == Ity_I8  || ty == Ity_I16 ||
2284           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
2285          HReg r_dst = newVRegI(env);
2286          PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
2287                                           GuestStatePtr(mode64) );
2288          addInstr(env, PPCInstr_Load( toUChar(sizeofIRType(ty)),
2289                                       r_dst, am_addr, mode64 ));
2290          return r_dst;
2291       }
2292       break;
2293    }
2294 
2295    case Iex_GetI: {
2296       PPCAMode* src_am
2297          = genGuestArrayOffset( env, e->Iex.GetI.descr,
2298                                      e->Iex.GetI.ix, e->Iex.GetI.bias );
2299       HReg r_dst = newVRegI(env);
2300       if (mode64 && ty == Ity_I64) {
2301          addInstr(env, PPCInstr_Load( toUChar(8),
2302                                       r_dst, src_am, mode64 ));
2303          return r_dst;
2304       }
2305       if ((!mode64) && ty == Ity_I32) {
2306          addInstr(env, PPCInstr_Load( toUChar(4),
2307                                       r_dst, src_am, mode64 ));
2308          return r_dst;
2309       }
2310       break;
2311    }
2312 
2313    /* --------- CCALL --------- */
2314    case Iex_CCall: {
2315       vassert(ty == e->Iex.CCall.retty); /* well-formedness of IR */
2316 
2317       /* be very restrictive for now.  Only 32/64-bit ints allowed for
2318          args, and 32 bits or host machine word for return type. */
2319       if (!(ty == Ity_I32 || (mode64 && ty == Ity_I64)))
2320          goto irreducible;
2321 
2322       /* Marshal args, do the call, clear stack. */
2323       UInt   addToSp = 0;
2324       RetLoc rloc    = mk_RetLoc_INVALID();
2325       doHelperCall( &addToSp, &rloc, env, NULL/*guard*/,
2326                     e->Iex.CCall.cee, e->Iex.CCall.retty, e->Iex.CCall.args );
2327       vassert(is_sane_RetLoc(rloc));
2328       vassert(rloc.pri == RLPri_Int);
2329       vassert(addToSp == 0);
2330 
2331       /* GPR3 now holds the destination address from Pin_Goto */
2332       HReg r_dst = newVRegI(env);
2333       addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
2334       return r_dst;
2335    }
2336 
2337    /* --------- LITERAL --------- */
2338    /* 32/16/8-bit literals */
2339    case Iex_Const: {
2340       Long l;
2341       HReg r_dst = newVRegI(env);
2342       IRConst* con = e->Iex.Const.con;
2343       switch (con->tag) {
2344          case Ico_U64: if (!mode64) goto irreducible;
2345                        l = (Long)            con->Ico.U64; break;
2346          case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
2347          case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
2348          case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
2349          default:      vpanic("iselIntExpr_R.const(ppc)");
2350       }
2351       addInstr(env, PPCInstr_LI(r_dst, (ULong)l, mode64));
2352       return r_dst;
2353    }
2354 
2355    /* --------- MULTIPLEX --------- */
2356    case Iex_ITE: { // VFD
2357       if ((ty == Ity_I8  || ty == Ity_I16 ||
2358            ty == Ity_I32 || ((ty == Ity_I64) && mode64)) &&
2359           typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) {
2360          PPCRI* r1    = iselWordExpr_RI(env, e->Iex.ITE.iftrue);
2361          HReg   r0    = iselWordExpr_R(env, e->Iex.ITE.iffalse);
2362          HReg   r_dst = newVRegI(env);
2363          addInstr(env, mk_iMOVds_RR(r_dst,r0));
2364          PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond);
2365          addInstr(env, PPCInstr_CMov(cc, r_dst, r1));
2366          return r_dst;
2367       }
2368       break;
2369    }
2370 
2371    default:
2372       break;
2373    } /* switch (e->tag) */
2374 
2375 
2376    /* We get here if no pattern matched. */
2377  irreducible:
2378    ppIRExpr(e);
2379    vpanic("iselIntExpr_R(ppc): cannot reduce tree");
2380 }
2381 
2382 
2383 /*---------------------------------------------------------*/
2384 /*--- ISEL: Integer expression auxiliaries              ---*/
2385 /*---------------------------------------------------------*/
2386 
2387 /* --------------------- AMODEs --------------------- */
2388 
2389 /* Return an AMode which computes the value of the specified
2390    expression, possibly also adding insns to the code list as a
2391    result.  The expression may only be a word-size one.
2392 */
2393 
uInt_fits_in_16_bits(UInt u)2394 static Bool uInt_fits_in_16_bits ( UInt u )
2395 {
2396    /* Is u the same as the sign-extend of its lower 16 bits? */
2397    Int i = u & 0xFFFF;
2398    i <<= 16;
2399    i >>= 16;
2400    return toBool(u == (UInt)i);
2401 }
2402 
uLong_fits_in_16_bits(ULong u)2403 static Bool uLong_fits_in_16_bits ( ULong u )
2404 {
2405    /* Is u the same as the sign-extend of its lower 16 bits? */
2406    Long i = u & 0xFFFFULL;
2407    i <<= 48;
2408    i >>= 48;
2409    return toBool(u == (ULong)i);
2410 }
2411 
uLong_is_4_aligned(ULong u)2412 static Bool uLong_is_4_aligned ( ULong u )
2413 {
2414    return toBool((u & 3ULL) == 0);
2415 }
2416 
sane_AMode(ISelEnv * env,PPCAMode * am)2417 static Bool sane_AMode ( ISelEnv* env, PPCAMode* am )
2418 {
2419    Bool mode64 = env->mode64;
2420    switch (am->tag) {
2421    case Pam_IR:
2422       /* Using uInt_fits_in_16_bits in 64-bit mode seems a bit bogus,
2423          somehow, but I think it's OK. */
2424       return toBool( hregClass(am->Pam.IR.base) == HRcGPR(mode64) &&
2425                      hregIsVirtual(am->Pam.IR.base) &&
2426                      uInt_fits_in_16_bits(am->Pam.IR.index) );
2427    case Pam_RR:
2428       return toBool( hregClass(am->Pam.RR.base) == HRcGPR(mode64) &&
2429                      hregIsVirtual(am->Pam.RR.base) &&
2430                      hregClass(am->Pam.RR.index) == HRcGPR(mode64) &&
2431                      hregIsVirtual(am->Pam.RR.index) );
2432    default:
2433       vpanic("sane_AMode: unknown ppc amode tag");
2434    }
2435 }
2436 
2437 static
iselWordExpr_AMode(ISelEnv * env,IRExpr * e,IRType xferTy)2438 PPCAMode* iselWordExpr_AMode ( ISelEnv* env, IRExpr* e, IRType xferTy )
2439 {
2440    PPCAMode* am = iselWordExpr_AMode_wrk(env, e, xferTy);
2441    vassert(sane_AMode(env, am));
2442    return am;
2443 }
2444 
2445 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_AMode_wrk(ISelEnv * env,IRExpr * e,IRType xferTy)2446 static PPCAMode* iselWordExpr_AMode_wrk ( ISelEnv* env, IRExpr* e, IRType xferTy )
2447 {
2448    IRType ty = typeOfIRExpr(env->type_env,e);
2449 
2450    if (env->mode64) {
2451 
2452       /* If the data load/store type is I32 or I64, this amode might
2453          be destined for use in ld/ldu/lwa/st/stu.  In which case
2454          insist that if it comes out as an _IR, the immediate must
2455          have its bottom two bits be zero.  This does assume that for
2456          any other type (I8/I16/I128/F32/F64/V128) the amode will not
2457          be parked in any such instruction.  But that seems a
2458          reasonable assumption.  */
2459       Bool aligned4imm = toBool(xferTy == Ity_I32 || xferTy == Ity_I64);
2460 
2461       vassert(ty == Ity_I64);
2462 
2463       /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
2464       if (e->tag == Iex_Binop
2465           && e->Iex.Binop.op == Iop_Add64
2466           && e->Iex.Binop.arg2->tag == Iex_Const
2467           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
2468           && (aligned4imm  ? uLong_is_4_aligned(e->Iex.Binop.arg2
2469                                                  ->Iex.Const.con->Ico.U64)
2470                            : True)
2471           && uLong_fits_in_16_bits(e->Iex.Binop.arg2
2472                                     ->Iex.Const.con->Ico.U64)) {
2473          return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
2474                              iselWordExpr_R(env, e->Iex.Binop.arg1) );
2475       }
2476 
2477       /* Add64(expr,expr) */
2478       if (e->tag == Iex_Binop
2479           && e->Iex.Binop.op == Iop_Add64) {
2480          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
2481          HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2482          return PPCAMode_RR( r_idx, r_base );
2483       }
2484 
2485    } else {
2486 
2487       vassert(ty == Ity_I32);
2488 
2489       /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
2490       if (e->tag == Iex_Binop
2491           && e->Iex.Binop.op == Iop_Add32
2492           && e->Iex.Binop.arg2->tag == Iex_Const
2493           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
2494           && uInt_fits_in_16_bits(e->Iex.Binop.arg2
2495                                    ->Iex.Const.con->Ico.U32)) {
2496          return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
2497                              iselWordExpr_R(env, e->Iex.Binop.arg1) );
2498       }
2499 
2500       /* Add32(expr,expr) */
2501       if (e->tag == Iex_Binop
2502           && e->Iex.Binop.op == Iop_Add32) {
2503          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
2504          HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2505          return PPCAMode_RR( r_idx, r_base );
2506       }
2507 
2508    }
2509 
2510    /* Doesn't match anything in particular.  Generate it into
2511       a register and use that. */
2512    return PPCAMode_IR( 0, iselWordExpr_R(env,e) );
2513 }
2514 
2515 
2516 /* --------------------- RH --------------------- */
2517 
2518 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
2519    (reg-or-halfword-immediate).  It's important to specify whether the
2520    immediate is to be regarded as signed or not.  If yes, this will
2521    never return -32768 as an immediate; this guaranteed that all
2522    signed immediates that are return can have their sign inverted if
2523    need be. */
2524 
iselWordExpr_RH(ISelEnv * env,Bool syned,IRExpr * e)2525 static PPCRH* iselWordExpr_RH ( ISelEnv* env, Bool syned, IRExpr* e )
2526 {
2527    PPCRH* ri = iselWordExpr_RH_wrk(env, syned, e);
2528    /* sanity checks ... */
2529    switch (ri->tag) {
2530    case Prh_Imm:
2531       vassert(ri->Prh.Imm.syned == syned);
2532       if (syned)
2533          vassert(ri->Prh.Imm.imm16 != 0x8000);
2534       return ri;
2535    case Prh_Reg:
2536       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2537       vassert(hregIsVirtual(ri->Prh.Reg.reg));
2538       return ri;
2539    default:
2540       vpanic("iselIntExpr_RH: unknown ppc RH tag");
2541    }
2542 }
2543 
2544 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH_wrk(ISelEnv * env,Bool syned,IRExpr * e)2545 static PPCRH* iselWordExpr_RH_wrk ( ISelEnv* env, Bool syned, IRExpr* e )
2546 {
2547    ULong u;
2548    Long  l;
2549    IRType ty = typeOfIRExpr(env->type_env,e);
2550    vassert(ty == Ity_I8  || ty == Ity_I16 ||
2551            ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2552 
2553    /* special case: immediate */
2554    if (e->tag == Iex_Const) {
2555       IRConst* con = e->Iex.Const.con;
2556       /* What value are we aiming to generate? */
2557       switch (con->tag) {
2558       /* Note: Not sign-extending - we carry 'syned' around */
2559       case Ico_U64: vassert(env->mode64);
2560                     u =              con->Ico.U64; break;
2561       case Ico_U32: u = 0xFFFFFFFF & con->Ico.U32; break;
2562       case Ico_U16: u = 0x0000FFFF & con->Ico.U16; break;
2563       case Ico_U8:  u = 0x000000FF & con->Ico.U8; break;
2564       default:      vpanic("iselIntExpr_RH.Iex_Const(ppch)");
2565       }
2566       l = (Long)u;
2567       /* Now figure out if it's representable. */
2568       if (!syned && u <= 65535) {
2569          return PPCRH_Imm(False/*unsigned*/, toUShort(u & 0xFFFF));
2570       }
2571       if (syned && l >= -32767 && l <= 32767) {
2572          return PPCRH_Imm(True/*signed*/, toUShort(u & 0xFFFF));
2573       }
2574       /* no luck; use the Slow Way. */
2575    }
2576 
2577    /* default case: calculate into a register and return that */
2578    return PPCRH_Reg( iselWordExpr_R ( env, e ) );
2579 }
2580 
2581 
2582 /* --------------------- RIs --------------------- */
2583 
2584 /* Calculate an expression into an PPCRI operand.  As with
2585    iselIntExpr_R, the expression can have type 32, 16 or 8 bits, or,
2586    in 64-bit mode, 64 bits. */
2587 
iselWordExpr_RI(ISelEnv * env,IRExpr * e)2588 static PPCRI* iselWordExpr_RI ( ISelEnv* env, IRExpr* e )
2589 {
2590    PPCRI* ri = iselWordExpr_RI_wrk(env, e);
2591    /* sanity checks ... */
2592    switch (ri->tag) {
2593    case Pri_Imm:
2594       return ri;
2595    case Pri_Reg:
2596       vassert(hregClass(ri->Pri.Reg) == HRcGPR(env->mode64));
2597       vassert(hregIsVirtual(ri->Pri.Reg));
2598       return ri;
2599    default:
2600       vpanic("iselIntExpr_RI: unknown ppc RI tag");
2601    }
2602 }
2603 
2604 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RI_wrk(ISelEnv * env,IRExpr * e)2605 static PPCRI* iselWordExpr_RI_wrk ( ISelEnv* env, IRExpr* e )
2606 {
2607    Long  l;
2608    IRType ty = typeOfIRExpr(env->type_env,e);
2609    vassert(ty == Ity_I8  || ty == Ity_I16 ||
2610            ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
2611 
2612    /* special case: immediate */
2613    if (e->tag == Iex_Const) {
2614       IRConst* con = e->Iex.Const.con;
2615       switch (con->tag) {
2616       case Ico_U64: vassert(env->mode64);
2617                     l = (Long)            con->Ico.U64; break;
2618       case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
2619       case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
2620       case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
2621       default:      vpanic("iselIntExpr_RI.Iex_Const(ppch)");
2622       }
2623       return PPCRI_Imm((ULong)l);
2624    }
2625 
2626    /* default case: calculate into a register and return that */
2627    return PPCRI_Reg( iselWordExpr_R ( env, e ) );
2628 }
2629 
2630 
2631 /* --------------------- RH5u --------------------- */
2632 
2633 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
2634    being an immediate in the range 1 .. 31 inclusive.  Used for doing
2635    shift amounts.  Only used in 32-bit mode. */
2636 
iselWordExpr_RH5u(ISelEnv * env,IRExpr * e)2637 static PPCRH* iselWordExpr_RH5u ( ISelEnv* env, IRExpr* e )
2638 {
2639    PPCRH* ri;
2640    vassert(!env->mode64);
2641    ri = iselWordExpr_RH5u_wrk(env, e);
2642    /* sanity checks ... */
2643    switch (ri->tag) {
2644    case Prh_Imm:
2645       vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 31);
2646       vassert(!ri->Prh.Imm.syned);
2647       return ri;
2648    case Prh_Reg:
2649       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2650       vassert(hregIsVirtual(ri->Prh.Reg.reg));
2651       return ri;
2652    default:
2653       vpanic("iselIntExpr_RH5u: unknown ppc RI tag");
2654    }
2655 }
2656 
2657 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH5u_wrk(ISelEnv * env,IRExpr * e)2658 static PPCRH* iselWordExpr_RH5u_wrk ( ISelEnv* env, IRExpr* e )
2659 {
2660    IRType ty = typeOfIRExpr(env->type_env,e);
2661    vassert(ty == Ity_I8);
2662 
2663    /* special case: immediate */
2664    if (e->tag == Iex_Const
2665        && e->Iex.Const.con->tag == Ico_U8
2666        && e->Iex.Const.con->Ico.U8 >= 1
2667        && e->Iex.Const.con->Ico.U8 <= 31) {
2668       return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
2669    }
2670 
2671    /* default case: calculate into a register and return that */
2672    return PPCRH_Reg( iselWordExpr_R ( env, e ) );
2673 }
2674 
2675 
2676 /* --------------------- RH6u --------------------- */
2677 
2678 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter
2679    being an immediate in the range 1 .. 63 inclusive.  Used for doing
2680    shift amounts.  Only used in 64-bit mode. */
2681 
iselWordExpr_RH6u(ISelEnv * env,IRExpr * e)2682 static PPCRH* iselWordExpr_RH6u ( ISelEnv* env, IRExpr* e )
2683 {
2684    PPCRH* ri;
2685    vassert(env->mode64);
2686    ri = iselWordExpr_RH6u_wrk(env, e);
2687    /* sanity checks ... */
2688    switch (ri->tag) {
2689    case Prh_Imm:
2690       vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 63);
2691       vassert(!ri->Prh.Imm.syned);
2692       return ri;
2693    case Prh_Reg:
2694       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
2695       vassert(hregIsVirtual(ri->Prh.Reg.reg));
2696       return ri;
2697    default:
2698       vpanic("iselIntExpr_RH6u: unknown ppc64 RI tag");
2699    }
2700 }
2701 
2702 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH6u_wrk(ISelEnv * env,IRExpr * e)2703 static PPCRH* iselWordExpr_RH6u_wrk ( ISelEnv* env, IRExpr* e )
2704 {
2705    IRType ty = typeOfIRExpr(env->type_env,e);
2706    vassert(ty == Ity_I8);
2707 
2708    /* special case: immediate */
2709    if (e->tag == Iex_Const
2710        && e->Iex.Const.con->tag == Ico_U8
2711        && e->Iex.Const.con->Ico.U8 >= 1
2712        && e->Iex.Const.con->Ico.U8 <= 63) {
2713       return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
2714    }
2715 
2716    /* default case: calculate into a register and return that */
2717    return PPCRH_Reg( iselWordExpr_R ( env, e ) );
2718 }
2719 
2720 
2721 /* --------------------- CONDCODE --------------------- */
2722 
2723 /* Generate code to evaluated a bit-typed expression, returning the
2724    condition code which would correspond when the expression would
2725    notionally have returned 1. */
2726 
iselCondCode(ISelEnv * env,IRExpr * e)2727 static PPCCondCode iselCondCode ( ISelEnv* env, IRExpr* e )
2728 {
2729    /* Uh, there's nothing we can sanity check here, unfortunately. */
2730    return iselCondCode_wrk(env,e);
2731 }
2732 
2733 /* DO NOT CALL THIS DIRECTLY ! */
iselCondCode_wrk(ISelEnv * env,IRExpr * e)2734 static PPCCondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
2735 {
2736    vassert(e);
2737    vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
2738 
2739    /* Constant 1:Bit */
2740    if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True) {
2741       // Make a compare that will always be true:
2742       HReg r_zero = newVRegI(env);
2743       addInstr(env, PPCInstr_LI(r_zero, 0, env->mode64));
2744       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2745                                  7/*cr*/, r_zero, PPCRH_Reg(r_zero)));
2746       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2747    }
2748 
2749    /* Not1(...) */
2750    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
2751       /* Generate code for the arg, and negate the test condition */
2752       PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg);
2753       cond.test = invertCondTest(cond.test);
2754       return cond;
2755    }
2756 
2757    /* --- patterns rooted at: 32to1 or 64to1 --- */
2758 
2759    /* 32to1, 64to1 */
2760    if (e->tag == Iex_Unop &&
2761        (e->Iex.Unop.op == Iop_32to1 || e->Iex.Unop.op == Iop_64to1)) {
2762       HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
2763       HReg tmp = newVRegI(env);
2764       /* could do better, probably -- andi. */
2765       addInstr(env, PPCInstr_Alu(Palu_AND, tmp,
2766                                  src, PPCRH_Imm(False,1)));
2767       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2768                                  7/*cr*/, tmp, PPCRH_Imm(False,1)));
2769       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2770    }
2771 
2772    /* --- patterns rooted at: CmpNEZ8 --- */
2773 
2774    /* CmpNEZ8(x) */
2775    /* Note this cloned as CmpNE8(x,0) below. */
2776    /* could do better -- andi. */
2777    if (e->tag == Iex_Unop
2778        && e->Iex.Unop.op == Iop_CmpNEZ8) {
2779       HReg arg = iselWordExpr_R(env, e->Iex.Unop.arg);
2780       HReg tmp = newVRegI(env);
2781       addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
2782                                  PPCRH_Imm(False,0xFF)));
2783       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2784                                  7/*cr*/, tmp, PPCRH_Imm(False,0)));
2785       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2786    }
2787 
2788    /* --- patterns rooted at: CmpNEZ32 --- */
2789 
2790    /* CmpNEZ32(x) */
2791    if (e->tag == Iex_Unop
2792        && e->Iex.Unop.op == Iop_CmpNEZ32) {
2793       HReg r1 = iselWordExpr_R(env, e->Iex.Unop.arg);
2794       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2795                                  7/*cr*/, r1, PPCRH_Imm(False,0)));
2796       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2797    }
2798 
2799    /* --- patterns rooted at: Cmp*32* --- */
2800 
2801    /* Cmp*32*(x,y) */
2802    if (e->tag == Iex_Binop
2803        && (e->Iex.Binop.op == Iop_CmpEQ32
2804            || e->Iex.Binop.op == Iop_CmpNE32
2805            || e->Iex.Binop.op == Iop_CmpLT32S
2806            || e->Iex.Binop.op == Iop_CmpLT32U
2807            || e->Iex.Binop.op == Iop_CmpLE32S
2808            || e->Iex.Binop.op == Iop_CmpLE32U)) {
2809       Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S ||
2810                     e->Iex.Binop.op == Iop_CmpLE32S);
2811       HReg   r1  = iselWordExpr_R(env, e->Iex.Binop.arg1);
2812       PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
2813       addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
2814                                  7/*cr*/, r1, ri2));
2815 
2816       switch (e->Iex.Binop.op) {
2817       case Iop_CmpEQ32:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
2818       case Iop_CmpNE32:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2819       case Iop_CmpLT32U: case Iop_CmpLT32S:
2820          return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
2821       case Iop_CmpLE32U: case Iop_CmpLE32S:
2822          return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
2823       default: vpanic("iselCondCode(ppc): CmpXX32");
2824       }
2825    }
2826 
2827    /* --- patterns rooted at: CmpNEZ64 --- */
2828 
2829    /* CmpNEZ64 */
2830    if (e->tag == Iex_Unop
2831        && e->Iex.Unop.op == Iop_CmpNEZ64) {
2832       if (!env->mode64) {
2833          HReg hi, lo;
2834          HReg tmp = newVRegI(env);
2835          iselInt64Expr( &hi, &lo, env, e->Iex.Unop.arg );
2836          addInstr(env, PPCInstr_Alu(Palu_OR, tmp, lo, PPCRH_Reg(hi)));
2837          addInstr(env, PPCInstr_Cmp(False/*sign*/, True/*32bit cmp*/,
2838                                     7/*cr*/, tmp,PPCRH_Imm(False,0)));
2839          return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2840       } else {  // mode64
2841          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
2842          addInstr(env, PPCInstr_Cmp(False/*sign*/, False/*64bit cmp*/,
2843                                     7/*cr*/, r_src,PPCRH_Imm(False,0)));
2844          return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2845       }
2846    }
2847 
2848    /* --- patterns rooted at: Cmp*64* --- */
2849 
2850    /* Cmp*64*(x,y) */
2851    if (e->tag == Iex_Binop
2852        && (e->Iex.Binop.op == Iop_CmpEQ64
2853            || e->Iex.Binop.op == Iop_CmpNE64
2854            || e->Iex.Binop.op == Iop_CmpLT64S
2855            || e->Iex.Binop.op == Iop_CmpLT64U
2856            || e->Iex.Binop.op == Iop_CmpLE64S
2857            || e->Iex.Binop.op == Iop_CmpLE64U)) {
2858       Bool   syned = (e->Iex.Binop.op == Iop_CmpLT64S ||
2859                       e->Iex.Binop.op == Iop_CmpLE64S);
2860       HReg    r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
2861       PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2);
2862       vassert(env->mode64);
2863       addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
2864                                  7/*cr*/, r1, ri2));
2865 
2866       switch (e->Iex.Binop.op) {
2867       case Iop_CmpEQ64:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
2868       case Iop_CmpNE64:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2869       case Iop_CmpLT64U: return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
2870       case Iop_CmpLE64U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
2871       default: vpanic("iselCondCode(ppc): CmpXX64");
2872       }
2873    }
2874 
2875    /* --- patterns rooted at: CmpNE8 --- */
2876 
2877    /* CmpNE8(x,0) */
2878    /* Note this is a direct copy of CmpNEZ8 above. */
2879    /* could do better -- andi. */
2880    if (e->tag == Iex_Binop
2881        && e->Iex.Binop.op == Iop_CmpNE8
2882        && isZeroU8(e->Iex.Binop.arg2)) {
2883       HReg arg = iselWordExpr_R(env, e->Iex.Binop.arg1);
2884       HReg tmp = newVRegI(env);
2885       addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
2886                                  PPCRH_Imm(False,0xFF)));
2887       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2888                                  7/*cr*/, tmp, PPCRH_Imm(False,0)));
2889       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
2890    }
2891 
2892    /* var */
2893    if (e->tag == Iex_RdTmp) {
2894       HReg r_src      = lookupIRTemp(env, e->Iex.RdTmp.tmp);
2895       HReg src_masked = newVRegI(env);
2896       addInstr(env,
2897                PPCInstr_Alu(Palu_AND, src_masked,
2898                             r_src, PPCRH_Imm(False,1)));
2899       addInstr(env,
2900                PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
2901                             7/*cr*/, src_masked, PPCRH_Imm(False,1)));
2902       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
2903    }
2904 
2905    vex_printf("iselCondCode(ppc): No such tag(%u)\n", e->tag);
2906    ppIRExpr(e);
2907    vpanic("iselCondCode(ppc)");
2908 }
2909 
2910 
2911 /*---------------------------------------------------------*/
2912 /*--- ISEL: Integer expressions (128 bit)               ---*/
2913 /*---------------------------------------------------------*/
2914 
2915 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
2916    which is returned as the first two parameters.  As with
2917    iselWordExpr_R, these may be either real or virtual regs; in any
2918    case they must not be changed by subsequent code emitted by the
2919    caller.  */
2920 
iselInt128Expr(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)2921 static void iselInt128Expr ( HReg* rHi, HReg* rLo,
2922                              ISelEnv* env, IRExpr* e )
2923 {
2924    vassert(env->mode64);
2925    iselInt128Expr_wrk(rHi, rLo, env, e);
2926 #  if 0
2927    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2928 #  endif
2929    vassert(hregClass(*rHi) == HRcGPR(env->mode64));
2930    vassert(hregIsVirtual(*rHi));
2931    vassert(hregClass(*rLo) == HRcGPR(env->mode64));
2932    vassert(hregIsVirtual(*rLo));
2933 }
2934 
2935 /* DO NOT CALL THIS DIRECTLY ! */
iselInt128Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)2936 static void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
2937                                  ISelEnv* env, IRExpr* e )
2938 {
2939    vassert(e);
2940    vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
2941 
2942    /* read 128-bit IRTemp */
2943    if (e->tag == Iex_RdTmp) {
2944       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
2945       return;
2946    }
2947 
2948    /* --------- BINARY ops --------- */
2949    if (e->tag == Iex_Binop) {
2950       switch (e->Iex.Binop.op) {
2951       /* 64 x 64 -> 128 multiply */
2952       case Iop_MullU64:
2953       case Iop_MullS64: {
2954          HReg     tLo     = newVRegI(env);
2955          HReg     tHi     = newVRegI(env);
2956          Bool     syned   = toBool(e->Iex.Binop.op == Iop_MullS64);
2957          HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
2958          HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2);
2959          addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
2960                                      False/*lo64*/, False/*64bit mul*/,
2961                                      tLo, r_srcL, r_srcR));
2962          addInstr(env, PPCInstr_MulL(syned,
2963                                      True/*hi64*/, False/*64bit mul*/,
2964                                      tHi, r_srcL, r_srcR));
2965          *rHi = tHi;
2966          *rLo = tLo;
2967          return;
2968       }
2969 
2970       /* 64HLto128(e1,e2) */
2971       case Iop_64HLto128:
2972          *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
2973          *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
2974          return;
2975       default:
2976          break;
2977       }
2978    } /* if (e->tag == Iex_Binop) */
2979 
2980 
2981    /* --------- UNARY ops --------- */
2982    if (e->tag == Iex_Unop) {
2983       switch (e->Iex.Unop.op) {
2984       default:
2985          break;
2986       }
2987    } /* if (e->tag == Iex_Unop) */
2988 
2989    vex_printf("iselInt128Expr(ppc64): No such tag(%u)\n", e->tag);
2990    ppIRExpr(e);
2991    vpanic("iselInt128Expr(ppc64)");
2992 }
2993 
2994 
2995 /*---------------------------------------------------------*/
2996 /*--- ISEL: Integer expressions (64 bit)                ---*/
2997 /*---------------------------------------------------------*/
2998 
2999 /* 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,IRExpr * e)3000 static void iselInt128Expr_to_32x4 ( HReg* rHi, HReg* rMedHi, HReg* rMedLo,
3001                                      HReg* rLo, ISelEnv* env, IRExpr* e )
3002 {
3003    vassert(!env->mode64);
3004    iselInt128Expr_to_32x4_wrk(rHi, rMedHi, rMedLo, rLo, env, e);
3005 #  if 0
3006    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3007 #  endif
3008    vassert(hregClass(*rHi) == HRcInt32);
3009    vassert(hregIsVirtual(*rHi));
3010    vassert(hregClass(*rMedHi) == HRcInt32);
3011    vassert(hregIsVirtual(*rMedHi));
3012    vassert(hregClass(*rMedLo) == HRcInt32);
3013    vassert(hregIsVirtual(*rMedLo));
3014    vassert(hregClass(*rLo) == HRcInt32);
3015    vassert(hregIsVirtual(*rLo));
3016 }
3017 
iselInt128Expr_to_32x4_wrk(HReg * rHi,HReg * rMedHi,HReg * rMedLo,HReg * rLo,ISelEnv * env,IRExpr * e)3018 static void iselInt128Expr_to_32x4_wrk ( HReg* rHi, HReg* rMedHi,
3019                                          HReg* rMedLo, HReg* rLo,
3020                                          ISelEnv* env, IRExpr* e )
3021 {
3022    vassert(e);
3023    vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
3024 
3025    /* read 128-bit IRTemp */
3026    if (e->tag == Iex_RdTmp) {
3027       lookupIRTempQuad( rHi, rMedHi, rMedLo, rLo, env, e->Iex.RdTmp.tmp);
3028       return;
3029    }
3030 
3031    if (e->tag == Iex_Binop) {
3032 
3033       IROp op_binop = e->Iex.Binop.op;
3034       switch (op_binop) {
3035       case Iop_64HLto128:
3036          iselInt64Expr(rHi, rMedHi, env, e->Iex.Binop.arg1);
3037          iselInt64Expr(rMedLo, rLo, env, e->Iex.Binop.arg2);
3038          return;
3039       default:
3040          vex_printf("iselInt128Expr_to_32x4_wrk: Binop case 0x%x not found\n",
3041                     op_binop);
3042          break;
3043       }
3044    }
3045 
3046    vex_printf("iselInt128Expr_to_32x4_wrk: e->tag 0x%x not found\n", e->tag);
3047    return;
3048 }
3049 
3050 /* 32-bit mode ONLY: compute a 64-bit value into a register pair,
3051    which is returned as the first two parameters.  As with
3052    iselIntExpr_R, these may be either real or virtual regs; in any
3053    case they must not be changed by subsequent code emitted by the
3054    caller.  */
3055 
iselInt64Expr(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)3056 static void iselInt64Expr ( HReg* rHi, HReg* rLo,
3057                             ISelEnv* env, IRExpr* e )
3058 {
3059    vassert(!env->mode64);
3060    iselInt64Expr_wrk(rHi, rLo, env, e);
3061 #  if 0
3062    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3063 #  endif
3064    vassert(hregClass(*rHi) == HRcInt32);
3065    vassert(hregIsVirtual(*rHi));
3066    vassert(hregClass(*rLo) == HRcInt32);
3067    vassert(hregIsVirtual(*rLo));
3068 }
3069 
3070 /* DO NOT CALL THIS DIRECTLY ! */
iselInt64Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)3071 static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
3072                                 ISelEnv* env, IRExpr* e )
3073 {
3074    vassert(e);
3075    vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
3076 
3077    /* 64-bit load */
3078    if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
3079       HReg tLo    = newVRegI(env);
3080       HReg tHi    = newVRegI(env);
3081       HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
3082       vassert(!env->mode64);
3083       addInstr(env, PPCInstr_Load( 4/*byte-load*/,
3084                                    tHi, PPCAMode_IR( 0, r_addr ),
3085                                    False/*32-bit insn please*/) );
3086       addInstr(env, PPCInstr_Load( 4/*byte-load*/,
3087                                    tLo, PPCAMode_IR( 4, r_addr ),
3088                                    False/*32-bit insn please*/) );
3089       *rHi = tHi;
3090       *rLo = tLo;
3091       return;
3092    }
3093 
3094    /* 64-bit literal */
3095    if (e->tag == Iex_Const) {
3096       ULong w64 = e->Iex.Const.con->Ico.U64;
3097       UInt  wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
3098       UInt  wLo = ((UInt)w64) & 0xFFFFFFFF;
3099       HReg  tLo = newVRegI(env);
3100       HReg  tHi = newVRegI(env);
3101       vassert(e->Iex.Const.con->tag == Ico_U64);
3102       addInstr(env, PPCInstr_LI(tHi, (Long)(Int)wHi, False/*mode32*/));
3103       addInstr(env, PPCInstr_LI(tLo, (Long)(Int)wLo, False/*mode32*/));
3104       *rHi = tHi;
3105       *rLo = tLo;
3106       return;
3107    }
3108 
3109    /* read 64-bit IRTemp */
3110    if (e->tag == Iex_RdTmp) {
3111       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
3112       return;
3113    }
3114 
3115    /* 64-bit GET */
3116    if (e->tag == Iex_Get) {
3117       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3118                                        GuestStatePtr(False/*mode32*/) );
3119       PPCAMode* am_addr4 = advance4(env, am_addr);
3120       HReg tLo = newVRegI(env);
3121       HReg tHi = newVRegI(env);
3122       addInstr(env, PPCInstr_Load( 4, tHi, am_addr,  False/*mode32*/ ));
3123       addInstr(env, PPCInstr_Load( 4, tLo, am_addr4, False/*mode32*/ ));
3124       *rHi = tHi;
3125       *rLo = tLo;
3126       return;
3127    }
3128 
3129    /* 64-bit ITE */
3130    if (e->tag == Iex_ITE) { // VFD
3131       HReg e0Lo, e0Hi, eXLo, eXHi;
3132       iselInt64Expr(&eXHi, &eXLo, env, e->Iex.ITE.iftrue);
3133       iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.ITE.iffalse);
3134       HReg tLo = newVRegI(env);
3135       HReg tHi = newVRegI(env);
3136       addInstr(env, mk_iMOVds_RR(tHi,e0Hi));
3137       addInstr(env, mk_iMOVds_RR(tLo,e0Lo));
3138       PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond);
3139       addInstr(env, PPCInstr_CMov(cc,tHi,PPCRI_Reg(eXHi)));
3140       addInstr(env, PPCInstr_CMov(cc,tLo,PPCRI_Reg(eXLo)));
3141       *rHi = tHi;
3142       *rLo = tLo;
3143       return;
3144    }
3145 
3146    /* --------- BINARY ops --------- */
3147    if (e->tag == Iex_Binop) {
3148       IROp op_binop = e->Iex.Binop.op;
3149       switch (op_binop) {
3150          /* 32 x 32 -> 64 multiply */
3151          case Iop_MullU32:
3152          case Iop_MullS32: {
3153             HReg     tLo     = newVRegI(env);
3154             HReg     tHi     = newVRegI(env);
3155             Bool     syned   = toBool(op_binop == Iop_MullS32);
3156             HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1);
3157             HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2);
3158             addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
3159                                         False/*lo32*/, True/*32bit mul*/,
3160                                         tLo, r_srcL, r_srcR));
3161             addInstr(env, PPCInstr_MulL(syned,
3162                                         True/*hi32*/, True/*32bit mul*/,
3163                                         tHi, r_srcL, r_srcR));
3164             *rHi = tHi;
3165             *rLo = tLo;
3166             return;
3167          }
3168 
3169          /* Or64/And64/Xor64 */
3170          case Iop_Or64:
3171          case Iop_And64:
3172          case Iop_Xor64: {
3173             HReg xLo, xHi, yLo, yHi;
3174             HReg tLo = newVRegI(env);
3175             HReg tHi = newVRegI(env);
3176             PPCAluOp op = (op_binop == Iop_Or64) ? Palu_OR :
3177                           (op_binop == Iop_And64) ? Palu_AND : Palu_XOR;
3178             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
3179             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
3180             addInstr(env, PPCInstr_Alu(op, tHi, xHi, PPCRH_Reg(yHi)));
3181             addInstr(env, PPCInstr_Alu(op, tLo, xLo, PPCRH_Reg(yLo)));
3182             *rHi = tHi;
3183             *rLo = tLo;
3184             return;
3185          }
3186 
3187          /* Add64 */
3188          case Iop_Add64: {
3189             HReg xLo, xHi, yLo, yHi;
3190             HReg tLo = newVRegI(env);
3191             HReg tHi = newVRegI(env);
3192             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
3193             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
3194             addInstr(env, PPCInstr_AddSubC( True/*add*/, True /*set carry*/,
3195                                             tLo, xLo, yLo));
3196             addInstr(env, PPCInstr_AddSubC( True/*add*/, False/*read carry*/,
3197                                             tHi, xHi, yHi));
3198             *rHi = tHi;
3199             *rLo = tLo;
3200             return;
3201          }
3202 
3203          /* 32HLto64(e1,e2) */
3204          case Iop_32HLto64:
3205             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
3206             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
3207             return;
3208 
3209          /* F64toI64[S|U] */
3210          case Iop_F64toI64S: case Iop_F64toI64U: {
3211             HReg      tLo     = newVRegI(env);
3212             HReg      tHi     = newVRegI(env);
3213             HReg      r1      = StackFramePtr(env->mode64);
3214             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3215             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3216             HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2);
3217             HReg      ftmp    = newVRegF(env);
3218 
3219             vassert(!env->mode64);
3220             /* Set host rounding mode */
3221             set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3222 
3223             sub_from_sp( env, 16 );
3224             addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
3225                                           (op_binop == Iop_F64toI64S) ? True : False,
3226                                           True, ftmp, fsrc));
3227             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
3228             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3229             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3230             add_to_sp( env, 16 );
3231 
3232             ///* Restore default FPU rounding. */
3233             //set_FPU_rounding_default( env );
3234             *rHi = tHi;
3235             *rLo = tLo;
3236             return;
3237          }
3238          case Iop_D64toI64S: {
3239             HReg      tLo     = newVRegI(env);
3240             HReg      tHi     = newVRegI(env);
3241             HReg      r1      = StackFramePtr(env->mode64);
3242             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3243             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3244             HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
3245             HReg tmp    = newVRegF(env);
3246 
3247             vassert(!env->mode64);
3248             set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
3249             addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTFIX, tmp, fr_src));
3250 
3251             sub_from_sp( env, 16 );
3252             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
3253             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3254             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3255             add_to_sp( env, 16 );
3256             *rHi = tHi;
3257             *rLo = tLo;
3258             return;
3259          }
3260          case Iop_D128toI64S: {
3261             PPCFpOp fpop = Pfp_DCTFIXQ;
3262             HReg r_srcHi = newVRegF(env);
3263             HReg r_srcLo = newVRegF(env);
3264             HReg tLo     = newVRegI(env);
3265             HReg tHi     = newVRegI(env);
3266             HReg ftmp    = newVRegF(env);
3267             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3268             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
3269 
3270             set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
3271             iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
3272             addInstr(env, PPCInstr_DfpD128toD64(fpop, ftmp, r_srcHi, r_srcLo));
3273 
3274             // put the D64 result into an integer register pair
3275             sub_from_sp( env, 16 );
3276             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
3277             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3278             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3279             add_to_sp( env, 16 );
3280             *rHi = tHi;
3281             *rLo = tLo;
3282             return;
3283          }
3284          default:
3285             break;
3286       }
3287    } /* if (e->tag == Iex_Binop) */
3288 
3289 
3290    /* --------- UNARY ops --------- */
3291    if (e->tag == Iex_Unop) {
3292       switch (e->Iex.Unop.op) {
3293 
3294       /* CmpwNEZ64(e) */
3295       case Iop_CmpwNEZ64: {
3296          HReg argHi, argLo;
3297          HReg tmp1  = newVRegI(env);
3298          HReg tmp2  = newVRegI(env);
3299          iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg);
3300          /* tmp1 = argHi | argLo */
3301          addInstr(env, PPCInstr_Alu(Palu_OR, tmp1, argHi, PPCRH_Reg(argLo)));
3302          /* tmp2 = (tmp1 | -tmp1) >>s 31 */
3303          addInstr(env, PPCInstr_Unary(Pun_NEG,tmp2,tmp1));
3304          addInstr(env, PPCInstr_Alu(Palu_OR, tmp2, tmp2, PPCRH_Reg(tmp1)));
3305          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3306                                      tmp2, tmp2, PPCRH_Imm(False, 31)));
3307          *rHi = tmp2;
3308          *rLo = tmp2; /* yes, really tmp2 */
3309          return;
3310       }
3311 
3312       /* Left64 */
3313       case Iop_Left64: {
3314          HReg argHi, argLo;
3315          HReg zero32 = newVRegI(env);
3316          HReg resHi  = newVRegI(env);
3317          HReg resLo  = newVRegI(env);
3318          iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg);
3319          vassert(env->mode64 == False);
3320          addInstr(env, PPCInstr_LI(zero32, 0, env->mode64));
3321          /* resHi:resLo = - argHi:argLo */
3322          addInstr(env, PPCInstr_AddSubC( False/*sub*/, True/*set carry*/,
3323                                          resLo, zero32, argLo ));
3324          addInstr(env, PPCInstr_AddSubC( False/*sub*/, False/*read carry*/,
3325                                          resHi, zero32, argHi ));
3326          /* resHi:resLo |= srcHi:srcLo */
3327          addInstr(env, PPCInstr_Alu(Palu_OR, resLo, resLo, PPCRH_Reg(argLo)));
3328          addInstr(env, PPCInstr_Alu(Palu_OR, resHi, resHi, PPCRH_Reg(argHi)));
3329          *rHi = resHi;
3330          *rLo = resLo;
3331          return;
3332       }
3333 
3334       /* 32Sto64(e) */
3335       case Iop_32Sto64: {
3336          HReg tHi = newVRegI(env);
3337          HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
3338          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3339                                      tHi, src, PPCRH_Imm(False,31)));
3340          *rHi = tHi;
3341          *rLo = src;
3342          return;
3343       }
3344       case Iop_ExtractExpD64: {
3345          HReg tmp    = newVRegF(env);
3346          HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
3347          HReg      tLo     = newVRegI(env);
3348          HReg      tHi     = newVRegI(env);
3349          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3350          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
3351 
3352          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DXEX, tmp, fr_src));
3353 
3354          // put the D64 result into a integer register pair
3355          sub_from_sp( env, 16 );
3356          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
3357          addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3358          addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3359          add_to_sp( env, 16 );
3360          *rHi = tHi;
3361          *rLo = tLo;
3362          return;
3363       }
3364       case Iop_ExtractExpD128: {
3365          HReg      r_srcHi;
3366          HReg      r_srcLo;
3367          HReg      tmp     = newVRegF(env);
3368          HReg      tLo     = newVRegI(env);
3369          HReg      tHi     = newVRegI(env);
3370          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3371          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
3372 
3373          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
3374          addInstr(env, PPCInstr_ExtractExpD128(Pfp_DXEXQ, tmp,
3375                                                   r_srcHi, r_srcLo));
3376 
3377          // put the D64 result into a integer register pair
3378          sub_from_sp( env, 16 );
3379          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
3380          addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
3381          addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
3382          add_to_sp( env, 16 );
3383          *rHi = tHi;
3384          *rLo = tLo;
3385          return;
3386       }
3387 
3388       /* 32Uto64(e) */
3389       case Iop_32Uto64: {
3390          HReg tHi = newVRegI(env);
3391          HReg tLo = iselWordExpr_R(env, e->Iex.Unop.arg);
3392          addInstr(env, PPCInstr_LI(tHi, 0, False/*mode32*/));
3393          *rHi = tHi;
3394          *rLo = tLo;
3395          return;
3396       }
3397 
3398       case Iop_128to64: {
3399          /* Narrow, return the low 64-bit half as a 32-bit
3400           * register pair */
3401          HReg r_Hi    = INVALID_HREG;
3402          HReg r_MedHi = INVALID_HREG;
3403          HReg r_MedLo = INVALID_HREG;
3404          HReg r_Lo    = INVALID_HREG;
3405 
3406          iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
3407                                 env, e->Iex.Unop.arg);
3408          *rHi = r_MedLo;
3409          *rLo = r_Lo;
3410          return;
3411       }
3412 
3413       case Iop_128HIto64: {
3414          /* Narrow, return the high 64-bit half as a 32-bit
3415           *  register pair */
3416          HReg r_Hi    = INVALID_HREG;
3417          HReg r_MedHi = INVALID_HREG;
3418          HReg r_MedLo = INVALID_HREG;
3419          HReg r_Lo    = INVALID_HREG;
3420 
3421          iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
3422                                 env, e->Iex.Unop.arg);
3423          *rHi = r_Hi;
3424          *rLo = r_MedHi;
3425          return;
3426       }
3427 
3428       /* V128{HI}to64 */
3429       case Iop_V128HIto64:
3430       case Iop_V128to64: {
3431          HReg r_aligned16;
3432          Int  off = e->Iex.Unop.op==Iop_V128HIto64 ? 0 : 8;
3433          HReg tLo = newVRegI(env);
3434          HReg tHi = newVRegI(env);
3435          HReg vec = iselVecExpr(env, e->Iex.Unop.arg);
3436          PPCAMode *am_off0, *am_offLO, *am_offHI;
3437          sub_from_sp( env, 32 );     // Move SP down 32 bytes
3438 
3439          // get a quadword aligned address within our stack space
3440          r_aligned16 = get_sp_aligned16( env );
3441          am_off0  = PPCAMode_IR( 0,     r_aligned16 );
3442          am_offHI = PPCAMode_IR( off,   r_aligned16 );
3443          am_offLO = PPCAMode_IR( off+4, r_aligned16 );
3444 
3445          // store as Vec128
3446          addInstr(env,
3447                   PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
3448 
3449          // load hi,lo words (of hi/lo half of vec) as Ity_I32's
3450          addInstr(env,
3451                   PPCInstr_Load( 4, tHi, am_offHI, False/*mode32*/ ));
3452          addInstr(env,
3453                   PPCInstr_Load( 4, tLo, am_offLO, False/*mode32*/ ));
3454 
3455          add_to_sp( env, 32 );       // Reset SP
3456          *rHi = tHi;
3457          *rLo = tLo;
3458          return;
3459       }
3460 
3461       /* could do better than this, but for now ... */
3462       case Iop_1Sto64: {
3463          HReg tLo = newVRegI(env);
3464          HReg tHi = newVRegI(env);
3465          PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg);
3466          addInstr(env, PPCInstr_Set(cond,tLo));
3467          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
3468                                      tLo, tLo, PPCRH_Imm(False,31)));
3469          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
3470                                      tLo, tLo, PPCRH_Imm(False,31)));
3471          addInstr(env, mk_iMOVds_RR(tHi, tLo));
3472          *rHi = tHi;
3473          *rLo = tLo;
3474          return;
3475       }
3476 
3477       case Iop_Not64: {
3478          HReg xLo, xHi;
3479          HReg tmpLo = newVRegI(env);
3480          HReg tmpHi = newVRegI(env);
3481          iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg);
3482          addInstr(env, PPCInstr_Unary(Pun_NOT,tmpLo,xLo));
3483          addInstr(env, PPCInstr_Unary(Pun_NOT,tmpHi,xHi));
3484          *rHi = tmpHi;
3485          *rLo = tmpLo;
3486          return;
3487       }
3488 
3489       /* ReinterpF64asI64(e) */
3490       /* Given an IEEE754 double, produce an I64 with the same bit
3491          pattern. */
3492       case Iop_ReinterpF64asI64: {
3493          PPCAMode *am_addr0, *am_addr1;
3494          HReg fr_src  = iselDblExpr(env, e->Iex.Unop.arg);
3495          HReg r_dstLo = newVRegI(env);
3496          HReg r_dstHi = newVRegI(env);
3497 
3498          sub_from_sp( env, 16 );     // Move SP down 16 bytes
3499          am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
3500          am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
3501 
3502          // store as F64
3503          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
3504                                         fr_src, am_addr0 ));
3505 
3506          // load hi,lo as Ity_I32's
3507          addInstr(env, PPCInstr_Load( 4, r_dstHi,
3508                                       am_addr0, False/*mode32*/ ));
3509          addInstr(env, PPCInstr_Load( 4, r_dstLo,
3510                                       am_addr1, False/*mode32*/ ));
3511          *rHi = r_dstHi;
3512          *rLo = r_dstLo;
3513 
3514          add_to_sp( env, 16 );       // Reset SP
3515          return;
3516       }
3517 
3518       case Iop_ReinterpD64asI64: {
3519          HReg fr_src  = iselDfp64Expr(env, e->Iex.Unop.arg);
3520          PPCAMode *am_addr0, *am_addr1;
3521          HReg r_dstLo = newVRegI(env);
3522          HReg r_dstHi = newVRegI(env);
3523 
3524 
3525          sub_from_sp( env, 16 );     // Move SP down 16 bytes
3526          am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
3527          am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
3528 
3529          // store as D64
3530          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
3531                                         fr_src, am_addr0 ));
3532 
3533          // load hi,lo as Ity_I32's
3534          addInstr(env, PPCInstr_Load( 4, r_dstHi,
3535                                       am_addr0, False/*mode32*/ ));
3536          addInstr(env, PPCInstr_Load( 4, r_dstLo,
3537                                       am_addr1, False/*mode32*/ ));
3538          *rHi = r_dstHi;
3539          *rLo = r_dstLo;
3540 
3541          add_to_sp( env, 16 );       // Reset SP
3542 
3543          return;
3544       }
3545 
3546       case Iop_BCDtoDPB: {
3547          PPCCondCode cc;
3548          UInt        argiregs;
3549          HReg        argregs[2];
3550          Int         argreg;
3551          HReg        tLo = newVRegI(env);
3552          HReg        tHi = newVRegI(env);
3553          HReg        tmpHi;
3554          HReg        tmpLo;
3555          ULong       target;
3556          Bool        mode64 = env->mode64;
3557 
3558          argregs[0] = hregPPC_GPR3(mode64);
3559          argregs[1] = hregPPC_GPR4(mode64);
3560 
3561          argiregs = 0;
3562          argreg = 0;
3563 
3564          iselInt64Expr( &tmpHi, &tmpLo, env, e->Iex.Unop.arg );
3565 
3566          argiregs |= ( 1 << (argreg+3 ) );
3567          addInstr( env, mk_iMOVds_RR( argregs[argreg++], tmpHi ) );
3568 
3569          argiregs |= ( 1 << (argreg+3 ) );
3570          addInstr( env, mk_iMOVds_RR( argregs[argreg], tmpLo ) );
3571 
3572          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
3573          target = toUInt( Ptr_to_ULong(h_calc_BCDtoDPB ) );
3574 
3575          addInstr( env, PPCInstr_Call( cc, (Addr64)target,
3576                                        argiregs,
3577                                        mk_RetLoc_simple(RLPri_2Int) ) );
3578          addInstr( env, mk_iMOVds_RR( tHi, argregs[argreg-1] ) );
3579          addInstr( env, mk_iMOVds_RR( tLo, argregs[argreg] ) );
3580 
3581          *rHi = tHi;
3582          *rLo = tLo;
3583          return;
3584       }
3585 
3586       case Iop_DPBtoBCD: {
3587          PPCCondCode cc;
3588          UInt        argiregs;
3589          HReg        argregs[2];
3590          Int         argreg;
3591          HReg        tLo = newVRegI(env);
3592          HReg        tHi = newVRegI(env);
3593          HReg        tmpHi;
3594          HReg        tmpLo;
3595          ULong       target;
3596          Bool        mode64 = env->mode64;
3597 
3598          argregs[0] = hregPPC_GPR3(mode64);
3599          argregs[1] = hregPPC_GPR4(mode64);
3600 
3601          argiregs = 0;
3602          argreg = 0;
3603 
3604          iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg);
3605 
3606          argiregs |= (1 << (argreg+3));
3607          addInstr(env, mk_iMOVds_RR( argregs[argreg++], tmpHi ));
3608 
3609          argiregs |= (1 << (argreg+3));
3610          addInstr(env, mk_iMOVds_RR( argregs[argreg], tmpLo));
3611 
3612          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
3613 
3614          target = toUInt( Ptr_to_ULong( h_calc_DPBtoBCD ) );
3615 
3616          addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs,
3617                                       mk_RetLoc_simple(RLPri_2Int) ) );
3618          addInstr(env, mk_iMOVds_RR(tHi, argregs[argreg-1]));
3619          addInstr(env, mk_iMOVds_RR(tLo, argregs[argreg]));
3620 
3621          *rHi = tHi;
3622          *rLo = tLo;
3623          return;
3624       }
3625 
3626       default:
3627          break;
3628       }
3629    } /* if (e->tag == Iex_Unop) */
3630 
3631    vex_printf("iselInt64Expr(ppc): No such tag(%u)\n", e->tag);
3632    ppIRExpr(e);
3633    vpanic("iselInt64Expr(ppc)");
3634 }
3635 
3636 
3637 /*---------------------------------------------------------*/
3638 /*--- ISEL: Floating point expressions (32 bit)         ---*/
3639 /*---------------------------------------------------------*/
3640 
3641 /* Nothing interesting here; really just wrappers for
3642    64-bit stuff. */
3643 
iselFltExpr(ISelEnv * env,IRExpr * e)3644 static HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
3645 {
3646    HReg r = iselFltExpr_wrk( env, e );
3647 #  if 0
3648    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3649 #  endif
3650    vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
3651    vassert(hregIsVirtual(r));
3652    return r;
3653 }
3654 
3655 /* DO NOT CALL THIS DIRECTLY */
iselFltExpr_wrk(ISelEnv * env,IRExpr * e)3656 static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
3657 {
3658    Bool        mode64 = env->mode64;
3659 
3660    IRType ty = typeOfIRExpr(env->type_env,e);
3661    vassert(ty == Ity_F32);
3662 
3663    if (e->tag == Iex_RdTmp) {
3664       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3665    }
3666 
3667    if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
3668       PPCAMode* am_addr;
3669       HReg r_dst = newVRegF(env);
3670       vassert(e->Iex.Load.ty == Ity_F32);
3671       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F32/*xfer*/);
3672       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
3673       return r_dst;
3674    }
3675 
3676    if (e->tag == Iex_Get) {
3677       HReg r_dst = newVRegF(env);
3678       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3679                                        GuestStatePtr(env->mode64) );
3680       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4, r_dst, am_addr ));
3681       return r_dst;
3682    }
3683 
3684    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
3685       /* This is quite subtle.  The only way to do the relevant
3686          truncation is to do a single-precision store and then a
3687          double precision load to get it back into a register.  The
3688          problem is, if the data is then written to memory a second
3689          time, as in
3690 
3691             STbe(...) = TruncF64asF32(...)
3692 
3693          then will the second truncation further alter the value?  The
3694          answer is no: flds (as generated here) followed by fsts
3695          (generated for the STbe) is the identity function on 32-bit
3696          floats, so we are safe.
3697 
3698          Another upshot of this is that if iselStmt can see the
3699          entirety of
3700 
3701             STbe(...) = TruncF64asF32(arg)
3702 
3703          then it can short circuit having to deal with TruncF64asF32
3704          individually; instead just compute arg into a 64-bit FP
3705          register and do 'fsts' (since that itself does the
3706          truncation).
3707 
3708          We generate pretty poor code here (should be ok both for
3709          32-bit and 64-bit mode); but it is expected that for the most
3710          part the latter optimisation will apply and hence this code
3711          will not often be used.
3712       */
3713       HReg      fsrc    = iselDblExpr(env, e->Iex.Unop.arg);
3714       HReg      fdst    = newVRegF(env);
3715       PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
3716 
3717       sub_from_sp( env, 16 );
3718       // store as F32, hence truncating
3719       addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
3720                                      fsrc, zero_r1 ));
3721       // and reload.  Good huh?! (sigh)
3722       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4,
3723                                      fdst, zero_r1 ));
3724       add_to_sp( env, 16 );
3725       return fdst;
3726    }
3727 
3728    if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64UtoF32) {
3729       if (mode64) {
3730          HReg fdst = newVRegF(env);
3731          HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2);
3732          HReg r1   = StackFramePtr(env->mode64);
3733          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3734 
3735          /* Set host rounding mode */
3736          set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3737 
3738          sub_from_sp( env, 16 );
3739 
3740          addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
3741          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3742          addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3743                                        False, False,
3744                                        fdst, fdst));
3745 
3746          add_to_sp( env, 16 );
3747 
3748          ///* Restore default FPU rounding. */
3749          //set_FPU_rounding_default( env );
3750          return fdst;
3751       } else {
3752          /* 32-bit mode */
3753          HReg fdst = newVRegF(env);
3754          HReg isrcHi, isrcLo;
3755          HReg r1   = StackFramePtr(env->mode64);
3756          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3757          PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3758 
3759          iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2);
3760 
3761          /* Set host rounding mode */
3762          set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3763 
3764          sub_from_sp( env, 16 );
3765 
3766          addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
3767          addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
3768          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3769          addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3770                                        False, False,
3771                                        fdst, fdst));
3772 
3773          add_to_sp( env, 16 );
3774 
3775          ///* Restore default FPU rounding. */
3776          //set_FPU_rounding_default( env );
3777          return fdst;
3778       }
3779 
3780    }
3781 
3782    vex_printf("iselFltExpr(ppc): No such tag(%u)\n", e->tag);
3783    ppIRExpr(e);
3784    vpanic("iselFltExpr_wrk(ppc)");
3785 }
3786 
3787 
3788 /*---------------------------------------------------------*/
3789 /*--- ISEL: Floating point expressions (64 bit)         ---*/
3790 /*---------------------------------------------------------*/
3791 
3792 /* Compute a 64-bit floating point value into a register, the identity
3793    of which is returned.  As with iselIntExpr_R, the reg may be either
3794    real or virtual; in any case it must not be changed by subsequent
3795    code emitted by the caller.  */
3796 
3797 /* IEEE 754 formats.  From http://www.freesoft.org/CIE/RFC/1832/32.htm:
3798 
3799     Type                  S (1 bit)   E (11 bits)   F (52 bits)
3800     ----                  ---------   -----------   -----------
3801     signalling NaN        u           2047 (max)    .0uuuuu---u
3802                                                     (with at least
3803                                                      one 1 bit)
3804     quiet NaN             u           2047 (max)    .1uuuuu---u
3805 
3806     negative infinity     1           2047 (max)    .000000---0
3807 
3808     positive infinity     0           2047 (max)    .000000---0
3809 
3810     negative zero         1           0             .000000---0
3811 
3812     positive zero         0           0             .000000---0
3813 */
3814 
iselDblExpr(ISelEnv * env,IRExpr * e)3815 static HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
3816 {
3817    HReg r = iselDblExpr_wrk( env, e );
3818 #  if 0
3819    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3820 #  endif
3821    vassert(hregClass(r) == HRcFlt64);
3822    vassert(hregIsVirtual(r));
3823    return r;
3824 }
3825 
3826 /* DO NOT CALL THIS DIRECTLY */
iselDblExpr_wrk(ISelEnv * env,IRExpr * e)3827 static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
3828 {
3829    Bool mode64 = env->mode64;
3830    IRType ty = typeOfIRExpr(env->type_env,e);
3831    vassert(e);
3832    vassert(ty == Ity_F64);
3833 
3834    if (e->tag == Iex_RdTmp) {
3835       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3836    }
3837 
3838    /* --------- LITERAL --------- */
3839    if (e->tag == Iex_Const) {
3840       union { UInt u32x2[2]; ULong u64; Double f64; } u;
3841       vassert(sizeof(u) == 8);
3842       vassert(sizeof(u.u64) == 8);
3843       vassert(sizeof(u.f64) == 8);
3844       vassert(sizeof(u.u32x2) == 8);
3845 
3846       if (e->Iex.Const.con->tag == Ico_F64) {
3847          u.f64 = e->Iex.Const.con->Ico.F64;
3848       }
3849       else if (e->Iex.Const.con->tag == Ico_F64i) {
3850          u.u64 = e->Iex.Const.con->Ico.F64i;
3851       }
3852       else
3853          vpanic("iselDblExpr(ppc): const");
3854 
3855       if (!mode64) {
3856          HReg r_srcHi = newVRegI(env);
3857          HReg r_srcLo = newVRegI(env);
3858          addInstr(env, PPCInstr_LI(r_srcHi, u.u32x2[0], mode64));
3859          addInstr(env, PPCInstr_LI(r_srcLo, u.u32x2[1], mode64));
3860          return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
3861       } else { // mode64
3862          HReg r_src = newVRegI(env);
3863          addInstr(env, PPCInstr_LI(r_src, u.u64, mode64));
3864          return mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
3865       }
3866    }
3867 
3868    /* --------- LOAD --------- */
3869    if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
3870       HReg r_dst = newVRegF(env);
3871       PPCAMode* am_addr;
3872       vassert(e->Iex.Load.ty == Ity_F64);
3873       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F64/*xfer*/);
3874       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
3875       return r_dst;
3876    }
3877 
3878    /* --------- GET --------- */
3879    if (e->tag == Iex_Get) {
3880       HReg r_dst = newVRegF(env);
3881       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
3882                                        GuestStatePtr(mode64) );
3883       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ));
3884       return r_dst;
3885    }
3886 
3887    /* --------- OPS --------- */
3888    if (e->tag == Iex_Qop) {
3889       PPCFpOp fpop = Pfp_INVALID;
3890       switch (e->Iex.Qop.details->op) {
3891          case Iop_MAddF64:    fpop = Pfp_MADDD; break;
3892          case Iop_MAddF64r32: fpop = Pfp_MADDS; break;
3893          case Iop_MSubF64:    fpop = Pfp_MSUBD; break;
3894          case Iop_MSubF64r32: fpop = Pfp_MSUBS; break;
3895          default: break;
3896       }
3897       if (fpop != Pfp_INVALID) {
3898          HReg r_dst  = newVRegF(env);
3899          HReg r_srcML  = iselDblExpr(env, e->Iex.Qop.details->arg2);
3900          HReg r_srcMR  = iselDblExpr(env, e->Iex.Qop.details->arg3);
3901          HReg r_srcAcc = iselDblExpr(env, e->Iex.Qop.details->arg4);
3902          set_FPU_rounding_mode( env, e->Iex.Qop.details->arg1 );
3903          addInstr(env, PPCInstr_FpMulAcc(fpop, r_dst,
3904                                                r_srcML, r_srcMR, r_srcAcc));
3905          return r_dst;
3906       }
3907    }
3908 
3909    if (e->tag == Iex_Triop) {
3910       IRTriop *triop = e->Iex.Triop.details;
3911       PPCFpOp fpop = Pfp_INVALID;
3912       switch (triop->op) {
3913          case Iop_AddF64:    fpop = Pfp_ADDD; break;
3914          case Iop_SubF64:    fpop = Pfp_SUBD; break;
3915          case Iop_MulF64:    fpop = Pfp_MULD; break;
3916          case Iop_DivF64:    fpop = Pfp_DIVD; break;
3917          case Iop_AddF64r32: fpop = Pfp_ADDS; break;
3918          case Iop_SubF64r32: fpop = Pfp_SUBS; break;
3919          case Iop_MulF64r32: fpop = Pfp_MULS; break;
3920          case Iop_DivF64r32: fpop = Pfp_DIVS; break;
3921          default: break;
3922       }
3923       if (fpop != Pfp_INVALID) {
3924          HReg r_dst  = newVRegF(env);
3925          HReg r_srcL = iselDblExpr(env, triop->arg2);
3926          HReg r_srcR = iselDblExpr(env, triop->arg3);
3927          set_FPU_rounding_mode( env, triop->arg1 );
3928          addInstr(env, PPCInstr_FpBinary(fpop, r_dst, r_srcL, r_srcR));
3929          return r_dst;
3930       }
3931    }
3932 
3933    if (e->tag == Iex_Binop) {
3934       PPCFpOp fpop = Pfp_INVALID;
3935       switch (e->Iex.Binop.op) {
3936       case Iop_SqrtF64:   fpop = Pfp_SQRT;   break;
3937       default: break;
3938       }
3939       if (fpop == Pfp_SQRT) {
3940          HReg fr_dst = newVRegF(env);
3941          HReg fr_src = iselDblExpr(env, e->Iex.Binop.arg2);
3942          set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3943          addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
3944          return fr_dst;
3945       }
3946    }
3947 
3948    if (e->tag == Iex_Binop) {
3949 
3950       if (e->Iex.Binop.op == Iop_RoundF64toF32) {
3951          HReg r_dst = newVRegF(env);
3952          HReg r_src = iselDblExpr(env, e->Iex.Binop.arg2);
3953          set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3954          addInstr(env, PPCInstr_FpRSP(r_dst, r_src));
3955          //set_FPU_rounding_default( env );
3956          return r_dst;
3957       }
3958 
3959       if (e->Iex.Binop.op == Iop_I64StoF64 || e->Iex.Binop.op == Iop_I64UtoF64) {
3960          if (mode64) {
3961             HReg fdst = newVRegF(env);
3962             HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2);
3963             HReg r1   = StackFramePtr(env->mode64);
3964             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3965 
3966             /* Set host rounding mode */
3967             set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3968 
3969             sub_from_sp( env, 16 );
3970 
3971             addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
3972             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
3973             addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
3974                                           e->Iex.Binop.op == Iop_I64StoF64,
3975                                           True/*fdst is 64 bit*/,
3976                                           fdst, fdst));
3977 
3978             add_to_sp( env, 16 );
3979 
3980             ///* Restore default FPU rounding. */
3981             //set_FPU_rounding_default( env );
3982             return fdst;
3983          } else {
3984             /* 32-bit mode */
3985             HReg fdst = newVRegF(env);
3986             HReg isrcHi, isrcLo;
3987             HReg r1   = StackFramePtr(env->mode64);
3988             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
3989             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
3990 
3991             iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2);
3992 
3993             /* Set host rounding mode */
3994             set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
3995 
3996             sub_from_sp( env, 16 );
3997 
3998             addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
3999             addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
4000             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
4001             addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
4002                                           e->Iex.Binop.op == Iop_I64StoF64,
4003                                           True/*fdst is 64 bit*/,
4004                                           fdst, fdst));
4005 
4006             add_to_sp( env, 16 );
4007 
4008             ///* Restore default FPU rounding. */
4009             //set_FPU_rounding_default( env );
4010             return fdst;
4011          }
4012       }
4013 
4014    }
4015 
4016    if (e->tag == Iex_Unop) {
4017       PPCFpOp fpop = Pfp_INVALID;
4018       switch (e->Iex.Unop.op) {
4019          case Iop_NegF64:     fpop = Pfp_NEG; break;
4020          case Iop_AbsF64:     fpop = Pfp_ABS; break;
4021          case Iop_Est5FRSqrt: fpop = Pfp_RSQRTE; break;
4022          case Iop_RoundF64toF64_NegINF:  fpop = Pfp_FRIM; break;
4023          case Iop_RoundF64toF64_PosINF:  fpop = Pfp_FRIP; break;
4024          case Iop_RoundF64toF64_NEAREST: fpop = Pfp_FRIN; break;
4025          case Iop_RoundF64toF64_ZERO:    fpop = Pfp_FRIZ; break;
4026          default: break;
4027       }
4028       if (fpop != Pfp_INVALID) {
4029          HReg fr_dst = newVRegF(env);
4030          HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
4031          addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
4032          return fr_dst;
4033       }
4034    }
4035 
4036    if (e->tag == Iex_Unop) {
4037       switch (e->Iex.Unop.op) {
4038          case Iop_ReinterpI64asF64: {
4039             /* Given an I64, produce an IEEE754 double with the same
4040                bit pattern. */
4041             if (!mode64) {
4042                HReg r_srcHi, r_srcLo;
4043                iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
4044                return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
4045             } else {
4046                HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
4047                return mk_LoadR64toFPR( env, r_src );
4048             }
4049          }
4050 
4051          case Iop_F32toF64: {
4052             if (e->Iex.Unop.arg->tag == Iex_Unop &&
4053                      e->Iex.Unop.arg->Iex.Unop.op == Iop_ReinterpI32asF32 ) {
4054                e = e->Iex.Unop.arg;
4055 
4056                HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
4057                HReg fr_dst = newVRegF(env);
4058                PPCAMode *am_addr;
4059 
4060                sub_from_sp( env, 16 );        // Move SP down 16 bytes
4061                am_addr = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4062 
4063                // store src as Ity_I32's
4064                addInstr(env, PPCInstr_Store( 4, am_addr, src, env->mode64 ));
4065 
4066                // load single precision float, but the end results loads into a
4067                // 64-bit FP register -- i.e., F64.
4068                addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, fr_dst, am_addr));
4069 
4070                add_to_sp( env, 16 );          // Reset SP
4071                return fr_dst;
4072             }
4073 
4074 
4075             /* this is a no-op */
4076             HReg res = iselFltExpr(env, e->Iex.Unop.arg);
4077             return res;
4078          }
4079          default:
4080             break;
4081       }
4082    }
4083 
4084    /* --------- MULTIPLEX --------- */
4085    if (e->tag == Iex_ITE) { // VFD
4086       if (ty == Ity_F64
4087           && typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) {
4088          HReg fr1    = iselDblExpr(env, e->Iex.ITE.iftrue);
4089          HReg fr0    = iselDblExpr(env, e->Iex.ITE.iffalse);
4090          HReg fr_dst = newVRegF(env);
4091          addInstr(env, PPCInstr_FpUnary( Pfp_MOV, fr_dst, fr0 ));
4092          PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond);
4093          addInstr(env, PPCInstr_FpCMov( cc, fr_dst, fr1 ));
4094          return fr_dst;
4095       }
4096    }
4097 
4098    vex_printf("iselDblExpr(ppc): No such tag(%u)\n", e->tag);
4099    ppIRExpr(e);
4100    vpanic("iselDblExpr_wrk(ppc)");
4101 }
4102 
iselDfp32Expr(ISelEnv * env,IRExpr * e)4103 static HReg iselDfp32Expr(ISelEnv* env, IRExpr* e)
4104 {
4105    HReg r = iselDfp32Expr_wrk( env, e );
4106    vassert(hregClass(r) == HRcFlt64);
4107    vassert( hregIsVirtual(r) );
4108    return r;
4109 }
4110 
4111 /* DO NOT CALL THIS DIRECTLY */
iselDfp32Expr_wrk(ISelEnv * env,IRExpr * e)4112 static HReg iselDfp32Expr_wrk(ISelEnv* env, IRExpr* e)
4113 {
4114    Bool mode64 = env->mode64;
4115    IRType ty = typeOfIRExpr( env->type_env, e );
4116 
4117    vassert( e );
4118    vassert( ty == Ity_D32 );
4119 
4120    /* --------- GET --------- */
4121    if (e->tag == Iex_Get) {
4122       HReg r_dst = newVRegF( env );
4123       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
4124                                        GuestStatePtr(mode64) );
4125       addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
4126       return r_dst;
4127    }
4128 
4129    /* --------- LOAD --------- */
4130    if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
4131       PPCAMode* am_addr;
4132       HReg r_dst = newVRegF(env);
4133       vassert(e->Iex.Load.ty == Ity_D32);
4134       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D32/*xfer*/);
4135       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
4136       return r_dst;
4137    }
4138 
4139    /* --------- OPS --------- */
4140    if (e->tag == Iex_Binop) {
4141       if (e->Iex.Binop.op == Iop_D64toD32) {
4142          HReg fr_dst = newVRegF(env);
4143          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
4144          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
4145          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DRSP, fr_dst, fr_src));
4146          return fr_dst;
4147       }
4148    }
4149 
4150    ppIRExpr( e );
4151    vpanic( "iselDfp32Expr_wrk(ppc)" );
4152 }
4153 
iselDfp64Expr(ISelEnv * env,IRExpr * e)4154 static HReg iselDfp64Expr(ISelEnv* env, IRExpr* e)
4155 {
4156    HReg r = iselDfp64Expr_wrk( env, e );
4157    vassert(hregClass(r) == HRcFlt64);
4158    vassert( hregIsVirtual(r) );
4159    return r;
4160 }
4161 
4162 /* DO NOT CALL THIS DIRECTLY */
iselDfp64Expr_wrk(ISelEnv * env,IRExpr * e)4163 static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e)
4164 {
4165    Bool mode64 = env->mode64;
4166    IRType ty = typeOfIRExpr( env->type_env, e );
4167    HReg r_dstHi, r_dstLo;
4168 
4169    vassert( e );
4170    vassert( ty == Ity_D64 );
4171 
4172    if (e->tag == Iex_RdTmp) {
4173       return lookupIRTemp( env, e->Iex.RdTmp.tmp );
4174    }
4175 
4176    /* --------- GET --------- */
4177    if (e->tag == Iex_Get) {
4178       HReg r_dst = newVRegF( env );
4179       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
4180                                        GuestStatePtr(mode64) );
4181       addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
4182       return r_dst;
4183    }
4184 
4185    if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
4186       PPCAMode* am_addr;
4187       HReg r_dst = newVRegF(env);
4188       vassert(e->Iex.Load.ty == Ity_D64);
4189       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D64/*xfer*/);
4190       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
4191       return r_dst;
4192    }
4193 
4194    /* --------- OPS --------- */
4195    if (e->tag == Iex_Qop) {
4196       HReg r_dst = newVRegF( env );
4197       return r_dst;
4198    }
4199 
4200    if (e->tag == Iex_Unop) {
4201       HReg fr_dst = newVRegF(env);
4202       switch (e->Iex.Unop.op) {
4203       case Iop_ReinterpI64asD64: {
4204          /* Given an I64, produce an IEEE754 DFP with the same
4205                bit pattern. */
4206          if (!mode64) {
4207             HReg r_srcHi, r_srcLo;
4208             iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
4209             return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
4210          } else {
4211             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
4212             return mk_LoadR64toFPR( env, r_src );
4213          }
4214       }
4215       case Iop_D32toD64: {
4216          HReg fr_src = iselDfp32Expr(env, e->Iex.Unop.arg);
4217          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
4218          return fr_dst;
4219       }
4220       case Iop_D128HItoD64:
4221          iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg );
4222          return r_dstHi;
4223       case Iop_D128LOtoD64:
4224          iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg );
4225          return r_dstLo;
4226       case Iop_InsertExpD64: {
4227          HReg fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
4228          HReg fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
4229 
4230          addInstr(env, PPCInstr_Dfp64Binary(Pfp_DIEX, fr_dst, fr_srcL,
4231 					    fr_srcR));
4232          return fr_dst;
4233        }
4234       default:
4235          vex_printf( "ERROR: iselDfp64Expr_wrk, UNKNOWN unop case %d\n",
4236                      e->Iex.Unop.op );
4237       }
4238    }
4239 
4240    if (e->tag == Iex_Binop) {
4241       PPCFpOp fpop = Pfp_INVALID;
4242       HReg fr_dst = newVRegF(env);
4243 
4244       switch (e->Iex.Binop.op) {
4245       case Iop_D128toD64:     fpop = Pfp_DRDPQ;  break;
4246       case Iop_D64toD32:      fpop = Pfp_DRSP;   break;
4247       case Iop_I64StoD64:     fpop = Pfp_DCFFIX; break;
4248       case Iop_RoundD64toInt: fpop = Pfp_DRINTN; break;
4249       default: break;
4250       }
4251       if (fpop == Pfp_DRDPQ) {
4252          HReg r_srcHi = newVRegF(env);
4253          HReg r_srcLo = newVRegF(env);
4254 
4255          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
4256          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
4257          addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
4258          return fr_dst;
4259 
4260       } else if (fpop == Pfp_DRINTN) {
4261          HReg fr_src = newVRegF(env);
4262          PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1);
4263 
4264          /* NOTE, this IOP takes a DFP value and rounds to the
4265           * neares floating point integer value, i.e. fractional part
4266           * is zero.  The result is a decimal floating point number.
4267           * the INT in the name is a bit misleading.
4268           */
4269          fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
4270          addInstr(env, PPCInstr_DfpRound(fr_dst, fr_src, r_rmc));
4271          return fr_dst;
4272 
4273       } else if (fpop == Pfp_DRSP) {
4274          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
4275          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
4276          addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
4277          return fr_dst;
4278 
4279       } else if (fpop == Pfp_DCFFIX) {
4280          HReg fr_src = newVRegF(env);
4281          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4282 
4283          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
4284          sub_from_sp( env, 16 );
4285 
4286          // put the I64 value into a floating point register
4287          if (mode64) {
4288             HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg2);
4289 
4290            addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
4291          } else {
4292             HReg tmpHi, tmpLo;
4293             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
4294 
4295             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Binop.arg2);
4296             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
4297             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
4298          }
4299 
4300          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8,  fr_src, zero_r1));
4301          addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
4302          add_to_sp( env, 16 );
4303          return fr_dst;
4304       }
4305 
4306       switch (e->Iex.Binop.op) {
4307       /* shift instructions D64, I32 -> D64 */
4308       case Iop_ShlD64: fpop = Pfp_DSCLI; break;
4309       case Iop_ShrD64: fpop = Pfp_DSCRI; break;
4310       default: break;
4311       }
4312       if (fpop != Pfp_INVALID) {
4313          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg1);
4314          PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2);
4315 
4316          /* shift value must be an immediate value */
4317          vassert(shift->tag == Pri_Imm);
4318 
4319          addInstr(env, PPCInstr_DfpShift(fpop, fr_dst, fr_src, shift));
4320          return fr_dst;
4321       }
4322 
4323       switch (e->Iex.Binop.op) {
4324       case Iop_InsertExpD64:
4325          fpop = Pfp_DIEX;
4326          break;
4327       default: 	break;
4328       }
4329       if (fpop != Pfp_INVALID) {
4330          HReg fr_srcL = newVRegF(env);
4331          HReg fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2);
4332          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4333          sub_from_sp( env, 16 );
4334 
4335          if (env->mode64) {
4336             // put the I64 value into a floating point reg
4337             HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg1);
4338 
4339             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
4340          } else {
4341             // put the I64 register pair into a floating point reg
4342             HReg tmpHi;
4343             HReg tmpLo;
4344             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
4345 
4346             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Binop.arg1);
4347             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*!mode64*/));
4348             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*!mode64*/));
4349          }
4350          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_srcL, zero_r1));
4351          addInstr(env, PPCInstr_Dfp64Binary(fpop, fr_dst, fr_srcL,
4352                                             fr_srcR));
4353          add_to_sp( env, 16 );
4354          return fr_dst;
4355       }
4356    }
4357 
4358    if (e->tag == Iex_Triop) {
4359       IRTriop *triop = e->Iex.Triop.details;
4360       PPCFpOp fpop = Pfp_INVALID;
4361 
4362       switch (triop->op) {
4363       case Iop_AddD64:
4364          fpop = Pfp_DFPADD;
4365          break;
4366       case Iop_SubD64:
4367          fpop = Pfp_DFPSUB;
4368          break;
4369       case Iop_MulD64:
4370          fpop = Pfp_DFPMUL;
4371          break;
4372       case Iop_DivD64:
4373          fpop = Pfp_DFPDIV;
4374          break;
4375       default:
4376          break;
4377       }
4378       if (fpop != Pfp_INVALID) {
4379          HReg r_dst = newVRegF( env );
4380          HReg r_srcL = iselDfp64Expr( env, triop->arg2 );
4381          HReg r_srcR = iselDfp64Expr( env, triop->arg3 );
4382 
4383          set_FPU_DFP_rounding_mode( env, triop->arg1 );
4384          addInstr( env, PPCInstr_Dfp64Binary( fpop, r_dst, r_srcL, r_srcR ) );
4385          return r_dst;
4386       }
4387 
4388       switch (triop->op) {
4389       case Iop_QuantizeD64:          fpop = Pfp_DQUA;  break;
4390       case Iop_SignificanceRoundD64: fpop = Pfp_RRDTR; break;
4391       default: break;
4392       }
4393       if (fpop == Pfp_DQUA) {
4394          HReg r_dst = newVRegF(env);
4395          HReg r_srcL = iselDfp64Expr(env, triop->arg2);
4396          HReg r_srcR = iselDfp64Expr(env, triop->arg3);
4397          PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1);
4398          addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR,
4399                                             rmc));
4400          return r_dst;
4401 
4402       } else if (fpop == Pfp_RRDTR) {
4403          HReg r_dst = newVRegF(env);
4404          HReg r_srcL = newVRegF(env);
4405          HReg r_srcR = iselDfp64Expr(env, triop->arg3);
4406          PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1);
4407          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4408          HReg i8_val = iselWordExpr_R(env, triop->arg2);
4409 
4410          /* Move I8 to float register to issue instruction */
4411          sub_from_sp( env, 16 );
4412          if (mode64)
4413             addInstr(env, PPCInstr_Store(8, zero_r1, i8_val, True/*mode64*/));
4414          else
4415             addInstr(env, PPCInstr_Store(4, zero_r1, i8_val, False/*mode32*/));
4416 
4417          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_srcL, zero_r1));
4418          add_to_sp( env, 16 );
4419 
4420          // will set TE and RMC when issuing instruction
4421          addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR, rmc));
4422          return r_dst;
4423       }
4424    }
4425 
4426    ppIRExpr( e );
4427    vpanic( "iselDfp64Expr_wrk(ppc)" );
4428 }
4429 
iselDfp128Expr(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)4430 static void iselDfp128Expr(HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e)
4431 {
4432    iselDfp128Expr_wrk( rHi, rLo, env, e );
4433    vassert( hregIsVirtual(*rHi) );
4434    vassert( hregIsVirtual(*rLo) );
4435 }
4436 
4437 /* DO NOT CALL THIS DIRECTLY */
iselDfp128Expr_wrk(HReg * rHi,HReg * rLo,ISelEnv * env,IRExpr * e)4438 static void iselDfp128Expr_wrk(HReg* rHi, HReg *rLo, ISelEnv* env, IRExpr* e)
4439 {
4440    vassert( e );
4441    vassert( typeOfIRExpr(env->type_env,e) == Ity_D128 );
4442 
4443    /* read 128-bit IRTemp */
4444    if (e->tag == Iex_RdTmp) {
4445       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp );
4446       return;
4447    }
4448 
4449    if (e->tag == Iex_Unop) {
4450       HReg r_dstHi = newVRegF(env);
4451       HReg r_dstLo = newVRegF(env);
4452 
4453       if (e->Iex.Unop.op == Iop_I64StoD128) {
4454          HReg fr_src = newVRegF(env);
4455          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4456 
4457          // put the I64 value into a floating point reg
4458          if (env->mode64) {
4459             HReg tmp   = iselWordExpr_R(env, e->Iex.Unop.arg);
4460             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
4461          } else {
4462             HReg tmpHi, tmpLo;
4463             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
4464 
4465             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg);
4466             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
4467             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
4468          }
4469 
4470          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_src, zero_r1));
4471          addInstr(env, PPCInstr_DfpI64StoD128(Pfp_DCFFIXQ, r_dstHi, r_dstLo,
4472                                               fr_src));
4473       }
4474 
4475       if (e->Iex.Unop.op == Iop_D64toD128) {
4476          HReg r_src = iselDfp64Expr(env, e->Iex.Unop.arg);
4477 
4478          /* Source is 64bit, result is 128 bit.  High 64bit source arg,
4479           * is ignored by the instruction.  Set high arg to r_src just
4480           * to meet the vassert tests.
4481           */
4482          addInstr(env, PPCInstr_Dfp128Unary(Pfp_DCTQPQ, r_dstHi, r_dstLo,
4483                                             r_src, r_src));
4484       }
4485       *rHi = r_dstHi;
4486       *rLo = r_dstLo;
4487       return;
4488    }
4489 
4490    /* --------- OPS --------- */
4491    if (e->tag == Iex_Binop) {
4492       HReg r_srcHi;
4493       HReg r_srcLo;
4494 
4495       switch (e->Iex.Binop.op) {
4496       case Iop_D64HLtoD128:
4497          r_srcHi = iselDfp64Expr( env, e->Iex.Binop.arg1 );
4498          r_srcLo = iselDfp64Expr( env, e->Iex.Binop.arg2 );
4499          *rHi = r_srcHi;
4500          *rLo = r_srcLo;
4501          return;
4502          break;
4503       case Iop_D128toD64: {
4504          PPCFpOp fpop = Pfp_DRDPQ;
4505          HReg fr_dst  = newVRegF(env);
4506 
4507          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
4508          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
4509          addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
4510 
4511          /* Need to meet the interface spec but the result is
4512           * just 64-bits so send the result back in both halfs.
4513           */
4514          *rHi = fr_dst;
4515          *rLo = fr_dst;
4516          return;
4517       }
4518       case Iop_ShlD128:
4519       case Iop_ShrD128: {
4520          HReg fr_dst_hi = newVRegF(env);
4521          HReg fr_dst_lo = newVRegF(env);
4522          PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2);
4523          PPCFpOp fpop = Pfp_DSCLIQ;  /* fix later if necessary */
4524 
4525          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1);
4526 
4527          if (e->Iex.Binop.op == Iop_ShrD128)
4528             fpop = Pfp_DSCRIQ;
4529 
4530          addInstr(env, PPCInstr_DfpShift128(fpop, fr_dst_hi, fr_dst_lo,
4531                                             r_srcHi, r_srcLo, shift));
4532 
4533          *rHi = fr_dst_hi;
4534          *rLo = fr_dst_lo;
4535          return;
4536       }
4537       case Iop_RoundD128toInt: {
4538          HReg r_dstHi = newVRegF(env);
4539          HReg r_dstLo = newVRegF(env);
4540          PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1);
4541 
4542          // will set R and RMC when issuing instruction
4543          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
4544 
4545          addInstr(env, PPCInstr_DfpRound128(r_dstHi, r_dstLo,
4546                                             r_srcHi, r_srcLo, r_rmc));
4547          *rHi = r_dstHi;
4548          *rLo = r_dstLo;
4549          return;
4550       }
4551       case Iop_InsertExpD128: {
4552          HReg r_dstHi = newVRegF(env);
4553          HReg r_dstLo = newVRegF(env);
4554          HReg r_srcL  = newVRegF(env);
4555          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4556          r_srcHi = newVRegF(env);
4557          r_srcLo = newVRegF(env);
4558 
4559          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2);
4560 
4561          /* Move I64 to float register to issue instruction */
4562          if (env->mode64) {
4563             HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg1);
4564             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
4565          } else {
4566             HReg tmpHi, tmpLo;
4567             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
4568 
4569             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg);
4570             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
4571             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
4572          }
4573 
4574          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_srcL, zero_r1));
4575          addInstr(env, PPCInstr_InsertExpD128(Pfp_DIEXQ,
4576                                               r_dstHi, r_dstLo,
4577                                               r_srcL, r_srcHi, r_srcLo));
4578          *rHi = r_dstHi;
4579          *rLo = r_dstLo;
4580          return;
4581       }
4582       default:
4583          vex_printf( "ERROR: iselDfp128Expr_wrk, UNKNOWN binop case %d\n",
4584                      e->Iex.Binop.op );
4585          break;
4586       }
4587    }
4588 
4589    if (e->tag == Iex_Triop) {
4590       IRTriop *triop = e->Iex.Triop.details;
4591       PPCFpOp fpop = Pfp_INVALID;
4592       HReg r_dstHi = newVRegF(env);
4593       HReg r_dstLo = newVRegF(env);
4594 
4595       switch (triop->op) {
4596       case Iop_AddD128:
4597          fpop = Pfp_DFPADDQ;
4598          break;
4599       case Iop_SubD128:
4600          fpop = Pfp_DFPSUBQ;
4601          break;
4602       case Iop_MulD128:
4603          fpop = Pfp_DFPMULQ;
4604          break;
4605       case Iop_DivD128:
4606          fpop = Pfp_DFPDIVQ;
4607          break;
4608       default:
4609          break;
4610       }
4611 
4612       if (fpop != Pfp_INVALID) {
4613          HReg r_srcRHi = newVRegV( env );
4614          HReg r_srcRLo = newVRegV( env );
4615 
4616          /* dst will be used to pass in the left operand and get the result. */
4617          iselDfp128Expr( &r_dstHi, &r_dstLo, env, triop->arg2 );
4618          iselDfp128Expr( &r_srcRHi, &r_srcRLo, env, triop->arg3 );
4619          set_FPU_DFP_rounding_mode( env, triop->arg1 );
4620          addInstr( env,
4621                    PPCInstr_Dfp128Binary( fpop, r_dstHi, r_dstLo,
4622                                           r_srcRHi, r_srcRLo ) );
4623          *rHi = r_dstHi;
4624          *rLo = r_dstLo;
4625          return;
4626       }
4627       switch (triop->op) {
4628       case Iop_QuantizeD128:          fpop = Pfp_DQUAQ;  break;
4629       case Iop_SignificanceRoundD128: fpop = Pfp_DRRNDQ; break;
4630       default: break;
4631       }
4632       if (fpop == Pfp_DQUAQ) {
4633          HReg r_srcHi = newVRegF(env);
4634          HReg r_srcLo = newVRegF(env);
4635          PPCRI* rmc = iselWordExpr_RI(env, triop->arg1);
4636 
4637          /* dst will be used to pass in the left operand and get the result */
4638          iselDfp128Expr(&r_dstHi, &r_dstLo, env, triop->arg2);
4639          iselDfp128Expr(&r_srcHi, &r_srcLo, env, triop->arg3);
4640 
4641          // will set RMC when issuing instruction
4642          addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
4643                                                r_srcHi, r_srcLo, rmc));
4644         *rHi = r_dstHi;
4645         *rLo = r_dstLo;
4646          return;
4647 
4648       } else if (fpop == Pfp_DRRNDQ) {
4649          HReg r_srcHi = newVRegF(env);
4650          HReg r_srcLo = newVRegF(env);
4651          PPCRI* rmc = iselWordExpr_RI(env, triop->arg1);
4652          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
4653          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
4654          HReg i8_val = iselWordExpr_R(env, triop->arg2);
4655          HReg r_zero = newVRegI( env );
4656 
4657          iselDfp128Expr(&r_srcHi, &r_srcLo, env, triop->arg3);
4658 
4659          /* dst will be used to pass in the left operand and get the result */
4660          /* Move I8 to float register to issue instruction.  Note, the
4661           * instruction only looks at the bottom 6 bits so we really don't
4662           * have to clear the upper bits since the iselWordExpr_R sets the
4663           * bottom 8-bits.
4664           */
4665          sub_from_sp( env, 16 );
4666 
4667          if (env->mode64)
4668             addInstr(env, PPCInstr_Store(4, four_r1, i8_val, True/*mode64*/));
4669          else
4670             addInstr(env, PPCInstr_Store(4, four_r1, i8_val, False/*mode32*/));
4671 
4672          /* Have to write to the upper bits to ensure they have been
4673           * initialized. The instruction ignores all but the lower 6-bits.
4674           */
4675          addInstr( env, PPCInstr_LI( r_zero, 0, env->mode64 ) );
4676          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dstHi, zero_r1));
4677          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dstLo, zero_r1));
4678 
4679          add_to_sp( env, 16 );
4680 
4681          // will set RMC when issuing instruction
4682          addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
4683                                                r_srcHi, r_srcLo, rmc));
4684          *rHi = r_dstHi;
4685          *rLo = r_dstLo;
4686          return;
4687       }
4688  }
4689 
4690    ppIRExpr( e );
4691    vpanic( "iselDfp128Expr(ppc64)" );
4692 }
4693 
4694 
4695 /*---------------------------------------------------------*/
4696 /*--- ISEL: SIMD (Vector) expressions, 128 bit.         ---*/
4697 /*---------------------------------------------------------*/
4698 
iselVecExpr(ISelEnv * env,IRExpr * e)4699 static HReg iselVecExpr ( ISelEnv* env, IRExpr* e )
4700 {
4701    HReg r = iselVecExpr_wrk( env, e );
4702 #  if 0
4703    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
4704 #  endif
4705    vassert(hregClass(r) == HRcVec128);
4706    vassert(hregIsVirtual(r));
4707    return r;
4708 }
4709 
4710 /* DO NOT CALL THIS DIRECTLY */
iselVecExpr_wrk(ISelEnv * env,IRExpr * e)4711 static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
4712 {
4713    Bool mode64 = env->mode64;
4714    PPCAvOp op = Pav_INVALID;
4715    PPCAvFpOp fpop = Pavfp_INVALID;
4716    IRType  ty = typeOfIRExpr(env->type_env,e);
4717    vassert(e);
4718    vassert(ty == Ity_V128);
4719 
4720    if (e->tag == Iex_RdTmp) {
4721       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
4722    }
4723 
4724    if (e->tag == Iex_Get) {
4725       /* Guest state vectors are 16byte aligned,
4726          so don't need to worry here */
4727       HReg dst = newVRegV(env);
4728       addInstr(env,
4729                PPCInstr_AvLdSt( True/*load*/, 16, dst,
4730                                 PPCAMode_IR( e->Iex.Get.offset,
4731                                              GuestStatePtr(mode64) )));
4732       return dst;
4733    }
4734 
4735    if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
4736       PPCAMode* am_addr;
4737       HReg v_dst = newVRegV(env);
4738       vassert(e->Iex.Load.ty == Ity_V128);
4739       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_V128/*xfer*/);
4740       addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, v_dst, am_addr));
4741       return v_dst;
4742    }
4743 
4744    if (e->tag == Iex_Unop) {
4745       switch (e->Iex.Unop.op) {
4746 
4747       case Iop_NotV128: {
4748          HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
4749          HReg dst = newVRegV(env);
4750          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, arg));
4751          return dst;
4752       }
4753 
4754       case Iop_CmpNEZ8x16: {
4755          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
4756          HReg zero = newVRegV(env);
4757          HReg dst  = newVRegV(env);
4758          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
4759          addInstr(env, PPCInstr_AvBin8x16(Pav_CMPEQU, dst, arg, zero));
4760          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
4761          return dst;
4762       }
4763 
4764       case Iop_CmpNEZ16x8: {
4765          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
4766          HReg zero = newVRegV(env);
4767          HReg dst  = newVRegV(env);
4768          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
4769          addInstr(env, PPCInstr_AvBin16x8(Pav_CMPEQU, dst, arg, zero));
4770          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
4771          return dst;
4772       }
4773 
4774       case Iop_CmpNEZ32x4: {
4775          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
4776          HReg zero = newVRegV(env);
4777          HReg dst  = newVRegV(env);
4778          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
4779          addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, dst, arg, zero));
4780          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
4781          return dst;
4782       }
4783 
4784       case Iop_CmpNEZ64x2: {
4785          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
4786          HReg zero = newVRegV(env);
4787          HReg dst  = newVRegV(env);
4788          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
4789          addInstr(env, PPCInstr_AvBin64x2(Pav_CMPEQU, dst, arg, zero));
4790          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
4791          return dst;
4792       }
4793 
4794       case Iop_Recip32Fx4:    fpop = Pavfp_RCPF;    goto do_32Fx4_unary;
4795       case Iop_RSqrt32Fx4:    fpop = Pavfp_RSQRTF;  goto do_32Fx4_unary;
4796       case Iop_I32UtoFx4:     fpop = Pavfp_CVTU2F;  goto do_32Fx4_unary;
4797       case Iop_I32StoFx4:     fpop = Pavfp_CVTS2F;  goto do_32Fx4_unary;
4798       case Iop_QFtoI32Ux4_RZ: fpop = Pavfp_QCVTF2U; goto do_32Fx4_unary;
4799       case Iop_QFtoI32Sx4_RZ: fpop = Pavfp_QCVTF2S; goto do_32Fx4_unary;
4800       case Iop_RoundF32x4_RM: fpop = Pavfp_ROUNDM;  goto do_32Fx4_unary;
4801       case Iop_RoundF32x4_RP: fpop = Pavfp_ROUNDP;  goto do_32Fx4_unary;
4802       case Iop_RoundF32x4_RN: fpop = Pavfp_ROUNDN;  goto do_32Fx4_unary;
4803       case Iop_RoundF32x4_RZ: fpop = Pavfp_ROUNDZ;  goto do_32Fx4_unary;
4804       do_32Fx4_unary:
4805       {
4806          HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
4807          HReg dst = newVRegV(env);
4808          addInstr(env, PPCInstr_AvUn32Fx4(fpop, dst, arg));
4809          return dst;
4810       }
4811 
4812       case Iop_32UtoV128: {
4813          HReg r_aligned16, r_zeros;
4814          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
4815          HReg   dst = newVRegV(env);
4816          PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
4817          sub_from_sp( env, 32 );     // Move SP down
4818 
4819          /* Get a quadword aligned address within our stack space */
4820          r_aligned16 = get_sp_aligned16( env );
4821          am_off0  = PPCAMode_IR( 0,  r_aligned16 );
4822          am_off4  = PPCAMode_IR( 4,  r_aligned16 );
4823          am_off8  = PPCAMode_IR( 8,  r_aligned16 );
4824          am_off12 = PPCAMode_IR( 12, r_aligned16 );
4825 
4826          /* Store zeros */
4827          r_zeros = newVRegI(env);
4828          addInstr(env, PPCInstr_LI(r_zeros, 0x0, mode64));
4829          addInstr(env, PPCInstr_Store( 4, am_off0, r_zeros, mode64 ));
4830          addInstr(env, PPCInstr_Store( 4, am_off4, r_zeros, mode64 ));
4831          addInstr(env, PPCInstr_Store( 4, am_off8, r_zeros, mode64 ));
4832 
4833          /* Store r_src in low word of quadword-aligned mem */
4834          addInstr(env, PPCInstr_Store( 4, am_off12, r_src, mode64 ));
4835 
4836          /* Load word into low word of quadword vector reg */
4837          addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off12 ));
4838 
4839          add_to_sp( env, 32 );       // Reset SP
4840          return dst;
4841       }
4842 
4843       case Iop_Dup8x16:
4844       case Iop_Dup16x8:
4845       case Iop_Dup32x4:
4846          return mk_AvDuplicateRI(env, e->Iex.Unop.arg);
4847 
4848       case Iop_CipherSV128: op = Pav_CIPHERSUBV128; goto do_AvCipherV128Un;
4849       do_AvCipherV128Un: {
4850          HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
4851          HReg dst = newVRegV(env);
4852          addInstr(env, PPCInstr_AvCipherV128Unary(op, dst, arg));
4853          return dst;
4854       }
4855 
4856       case Iop_Clz8Sx16: fpop = Pav_ZEROCNTBYTE;   goto do_zerocnt;
4857       case Iop_Clz16Sx8: fpop = Pav_ZEROCNTHALF;   goto do_zerocnt;
4858       case Iop_Clz32Sx4: fpop = Pav_ZEROCNTWORD;   goto do_zerocnt;
4859       case Iop_Clz64x2:  fpop = Pav_ZEROCNTDBL;    goto do_zerocnt;
4860       case Iop_PwBitMtxXpose64x2: fpop = Pav_BITMTXXPOSE;  goto do_zerocnt;
4861       do_zerocnt:
4862       {
4863         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
4864         HReg dst = newVRegV(env);
4865         addInstr(env, PPCInstr_AvUnary(fpop, dst, arg));
4866         return dst;
4867       }
4868 
4869       default:
4870          break;
4871       } /* switch (e->Iex.Unop.op) */
4872    } /* if (e->tag == Iex_Unop) */
4873 
4874    if (e->tag == Iex_Binop) {
4875       switch (e->Iex.Binop.op) {
4876 
4877       case Iop_64HLtoV128: {
4878          if (!mode64) {
4879             HReg     r3, r2, r1, r0, r_aligned16;
4880             PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
4881             HReg     dst = newVRegV(env);
4882             /* do this via the stack (easy, convenient, etc) */
4883             sub_from_sp( env, 32 );        // Move SP down
4884 
4885             // get a quadword aligned address within our stack space
4886             r_aligned16 = get_sp_aligned16( env );
4887             am_off0  = PPCAMode_IR( 0,  r_aligned16 );
4888             am_off4  = PPCAMode_IR( 4,  r_aligned16 );
4889             am_off8  = PPCAMode_IR( 8,  r_aligned16 );
4890             am_off12 = PPCAMode_IR( 12, r_aligned16 );
4891 
4892             /* Do the less significant 64 bits */
4893             iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2);
4894             addInstr(env, PPCInstr_Store( 4, am_off12, r0, mode64 ));
4895             addInstr(env, PPCInstr_Store( 4, am_off8,  r1, mode64 ));
4896             /* Do the more significant 64 bits */
4897             iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1);
4898             addInstr(env, PPCInstr_Store( 4, am_off4, r2, mode64 ));
4899             addInstr(env, PPCInstr_Store( 4, am_off0, r3, mode64 ));
4900 
4901             /* Fetch result back from stack. */
4902             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
4903 
4904             add_to_sp( env, 32 );          // Reset SP
4905             return dst;
4906          } else {
4907             HReg     rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
4908             HReg     rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
4909             HReg     dst = newVRegV(env);
4910             HReg     r_aligned16;
4911             PPCAMode *am_off0, *am_off8;
4912             /* do this via the stack (easy, convenient, etc) */
4913             sub_from_sp( env, 32 );        // Move SP down
4914 
4915             // get a quadword aligned address within our stack space
4916             r_aligned16 = get_sp_aligned16( env );
4917             am_off0  = PPCAMode_IR( 0,  r_aligned16 );
4918             am_off8  = PPCAMode_IR( 8,  r_aligned16 );
4919 
4920             /* Store 2*I64 to stack */
4921             addInstr(env, PPCInstr_Store( 8, am_off0, rHi, mode64 ));
4922             addInstr(env, PPCInstr_Store( 8, am_off8, rLo, mode64 ));
4923 
4924             /* Fetch result back from stack. */
4925             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
4926 
4927             add_to_sp( env, 32 );          // Reset SP
4928             return dst;
4929          }
4930       }
4931 
4932       case Iop_Max32Fx4:   fpop = Pavfp_MAXF;   goto do_32Fx4;
4933       case Iop_Min32Fx4:   fpop = Pavfp_MINF;   goto do_32Fx4;
4934       case Iop_CmpEQ32Fx4: fpop = Pavfp_CMPEQF; goto do_32Fx4;
4935       case Iop_CmpGT32Fx4: fpop = Pavfp_CMPGTF; goto do_32Fx4;
4936       case Iop_CmpGE32Fx4: fpop = Pavfp_CMPGEF; goto do_32Fx4;
4937       do_32Fx4:
4938       {
4939          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
4940          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
4941          HReg dst = newVRegV(env);
4942          addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
4943          return dst;
4944       }
4945 
4946       case Iop_CmpLE32Fx4: {
4947          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
4948          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
4949          HReg dst = newVRegV(env);
4950 
4951          /* stay consistent with native ppc compares:
4952             if a left/right lane holds a nan, return zeros for that lane
4953             so: le == NOT(gt OR isNan)
4954           */
4955          HReg isNanLR = newVRegV(env);
4956          HReg isNanL = isNan(env, argL);
4957          HReg isNanR = isNan(env, argR);
4958          addInstr(env, PPCInstr_AvBinary(Pav_OR, isNanLR,
4959                                          isNanL, isNanR));
4960 
4961          addInstr(env, PPCInstr_AvBin32Fx4(Pavfp_CMPGTF, dst,
4962                                            argL, argR));
4963          addInstr(env, PPCInstr_AvBinary(Pav_OR, dst, dst, isNanLR));
4964          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
4965          return dst;
4966       }
4967 
4968       case Iop_AndV128:    op = Pav_AND;      goto do_AvBin;
4969       case Iop_OrV128:     op = Pav_OR;       goto do_AvBin;
4970       case Iop_XorV128:    op = Pav_XOR;      goto do_AvBin;
4971       do_AvBin: {
4972          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
4973          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
4974          HReg dst  = newVRegV(env);
4975          addInstr(env, PPCInstr_AvBinary(op, dst, arg1, arg2));
4976          return dst;
4977       }
4978 
4979       case Iop_Shl8x16:    op = Pav_SHL;    goto do_AvBin8x16;
4980       case Iop_Shr8x16:    op = Pav_SHR;    goto do_AvBin8x16;
4981       case Iop_Sar8x16:    op = Pav_SAR;    goto do_AvBin8x16;
4982       case Iop_Rol8x16:    op = Pav_ROTL;   goto do_AvBin8x16;
4983       case Iop_InterleaveHI8x16: op = Pav_MRGHI;  goto do_AvBin8x16;
4984       case Iop_InterleaveLO8x16: op = Pav_MRGLO;  goto do_AvBin8x16;
4985       case Iop_Add8x16:    op = Pav_ADDU;   goto do_AvBin8x16;
4986       case Iop_QAdd8Ux16:  op = Pav_QADDU;  goto do_AvBin8x16;
4987       case Iop_QAdd8Sx16:  op = Pav_QADDS;  goto do_AvBin8x16;
4988       case Iop_Sub8x16:    op = Pav_SUBU;   goto do_AvBin8x16;
4989       case Iop_QSub8Ux16:  op = Pav_QSUBU;  goto do_AvBin8x16;
4990       case Iop_QSub8Sx16:  op = Pav_QSUBS;  goto do_AvBin8x16;
4991       case Iop_Avg8Ux16:   op = Pav_AVGU;   goto do_AvBin8x16;
4992       case Iop_Avg8Sx16:   op = Pav_AVGS;   goto do_AvBin8x16;
4993       case Iop_Max8Ux16:   op = Pav_MAXU;   goto do_AvBin8x16;
4994       case Iop_Max8Sx16:   op = Pav_MAXS;   goto do_AvBin8x16;
4995       case Iop_Min8Ux16:   op = Pav_MINU;   goto do_AvBin8x16;
4996       case Iop_Min8Sx16:   op = Pav_MINS;   goto do_AvBin8x16;
4997       case Iop_MullEven8Ux16: op = Pav_OMULU;  goto do_AvBin8x16;
4998       case Iop_MullEven8Sx16: op = Pav_OMULS;  goto do_AvBin8x16;
4999       case Iop_CmpEQ8x16:  op = Pav_CMPEQU; goto do_AvBin8x16;
5000       case Iop_CmpGT8Ux16: op = Pav_CMPGTU; goto do_AvBin8x16;
5001       case Iop_CmpGT8Sx16: op = Pav_CMPGTS; goto do_AvBin8x16;
5002       case Iop_PolynomialMulAdd8x16: op = Pav_POLYMULADD; goto do_AvBin8x16;
5003       do_AvBin8x16: {
5004          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
5005          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
5006          HReg dst  = newVRegV(env);
5007          addInstr(env, PPCInstr_AvBin8x16(op, dst, arg1, arg2));
5008          return dst;
5009       }
5010 
5011       case Iop_Shl16x8:    op = Pav_SHL;    goto do_AvBin16x8;
5012       case Iop_Shr16x8:    op = Pav_SHR;    goto do_AvBin16x8;
5013       case Iop_Sar16x8:    op = Pav_SAR;    goto do_AvBin16x8;
5014       case Iop_Rol16x8:    op = Pav_ROTL;   goto do_AvBin16x8;
5015       case Iop_NarrowBin16to8x16:    op = Pav_PACKUU;  goto do_AvBin16x8;
5016       case Iop_QNarrowBin16Uto8Ux16: op = Pav_QPACKUU; goto do_AvBin16x8;
5017       case Iop_QNarrowBin16Sto8Sx16: op = Pav_QPACKSS; goto do_AvBin16x8;
5018       case Iop_InterleaveHI16x8:  op = Pav_MRGHI;  goto do_AvBin16x8;
5019       case Iop_InterleaveLO16x8:  op = Pav_MRGLO;  goto do_AvBin16x8;
5020       case Iop_Add16x8:    op = Pav_ADDU;   goto do_AvBin16x8;
5021       case Iop_QAdd16Ux8:  op = Pav_QADDU;  goto do_AvBin16x8;
5022       case Iop_QAdd16Sx8:  op = Pav_QADDS;  goto do_AvBin16x8;
5023       case Iop_Sub16x8:    op = Pav_SUBU;   goto do_AvBin16x8;
5024       case Iop_QSub16Ux8:  op = Pav_QSUBU;  goto do_AvBin16x8;
5025       case Iop_QSub16Sx8:  op = Pav_QSUBS;  goto do_AvBin16x8;
5026       case Iop_Avg16Ux8:   op = Pav_AVGU;   goto do_AvBin16x8;
5027       case Iop_Avg16Sx8:   op = Pav_AVGS;   goto do_AvBin16x8;
5028       case Iop_Max16Ux8:   op = Pav_MAXU;   goto do_AvBin16x8;
5029       case Iop_Max16Sx8:   op = Pav_MAXS;   goto do_AvBin16x8;
5030       case Iop_Min16Ux8:   op = Pav_MINU;   goto do_AvBin16x8;
5031       case Iop_Min16Sx8:   op = Pav_MINS;   goto do_AvBin16x8;
5032       case Iop_MullEven16Ux8: op = Pav_OMULU;  goto do_AvBin16x8;
5033       case Iop_MullEven16Sx8: op = Pav_OMULS;  goto do_AvBin16x8;
5034       case Iop_CmpEQ16x8:  op = Pav_CMPEQU; goto do_AvBin16x8;
5035       case Iop_CmpGT16Ux8: op = Pav_CMPGTU; goto do_AvBin16x8;
5036       case Iop_CmpGT16Sx8: op = Pav_CMPGTS; goto do_AvBin16x8;
5037       case Iop_PolynomialMulAdd16x8: op = Pav_POLYMULADD; goto do_AvBin16x8;
5038       do_AvBin16x8: {
5039          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
5040          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
5041          HReg dst  = newVRegV(env);
5042          addInstr(env, PPCInstr_AvBin16x8(op, dst, arg1, arg2));
5043          return dst;
5044       }
5045 
5046       case Iop_Shl32x4:    op = Pav_SHL;    goto do_AvBin32x4;
5047       case Iop_Shr32x4:    op = Pav_SHR;    goto do_AvBin32x4;
5048       case Iop_Sar32x4:    op = Pav_SAR;    goto do_AvBin32x4;
5049       case Iop_Rol32x4:    op = Pav_ROTL;   goto do_AvBin32x4;
5050       case Iop_NarrowBin32to16x8:    op = Pav_PACKUU;  goto do_AvBin32x4;
5051       case Iop_QNarrowBin32Uto16Ux8: op = Pav_QPACKUU; goto do_AvBin32x4;
5052       case Iop_QNarrowBin32Sto16Sx8: op = Pav_QPACKSS; goto do_AvBin32x4;
5053       case Iop_InterleaveHI32x4:  op = Pav_MRGHI;  goto do_AvBin32x4;
5054       case Iop_InterleaveLO32x4:  op = Pav_MRGLO;  goto do_AvBin32x4;
5055       case Iop_Add32x4:    op = Pav_ADDU;   goto do_AvBin32x4;
5056       case Iop_QAdd32Ux4:  op = Pav_QADDU;  goto do_AvBin32x4;
5057       case Iop_QAdd32Sx4:  op = Pav_QADDS;  goto do_AvBin32x4;
5058       case Iop_Sub32x4:    op = Pav_SUBU;   goto do_AvBin32x4;
5059       case Iop_QSub32Ux4:  op = Pav_QSUBU;  goto do_AvBin32x4;
5060       case Iop_QSub32Sx4:  op = Pav_QSUBS;  goto do_AvBin32x4;
5061       case Iop_Avg32Ux4:   op = Pav_AVGU;   goto do_AvBin32x4;
5062       case Iop_Avg32Sx4:   op = Pav_AVGS;   goto do_AvBin32x4;
5063       case Iop_Max32Ux4:   op = Pav_MAXU;   goto do_AvBin32x4;
5064       case Iop_Max32Sx4:   op = Pav_MAXS;   goto do_AvBin32x4;
5065       case Iop_Min32Ux4:   op = Pav_MINU;   goto do_AvBin32x4;
5066       case Iop_Min32Sx4:   op = Pav_MINS;   goto do_AvBin32x4;
5067       case Iop_Mul32x4:    op = Pav_MULU;   goto do_AvBin32x4;
5068       case Iop_MullEven32Ux4: op = Pav_OMULU;  goto do_AvBin32x4;
5069       case Iop_MullEven32Sx4: op = Pav_OMULS;  goto do_AvBin32x4;
5070       case Iop_CmpEQ32x4:  op = Pav_CMPEQU; goto do_AvBin32x4;
5071       case Iop_CmpGT32Ux4: op = Pav_CMPGTU; goto do_AvBin32x4;
5072       case Iop_CmpGT32Sx4: op = Pav_CMPGTS; goto do_AvBin32x4;
5073       case Iop_CatOddLanes32x4:  op = Pav_CATODD;  goto do_AvBin32x4;
5074       case Iop_CatEvenLanes32x4: op = Pav_CATEVEN; goto do_AvBin32x4;
5075       case Iop_PolynomialMulAdd32x4: op = Pav_POLYMULADD; goto do_AvBin32x4;
5076       do_AvBin32x4: {
5077          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
5078          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
5079          HReg dst  = newVRegV(env);
5080          addInstr(env, PPCInstr_AvBin32x4(op, dst, arg1, arg2));
5081          return dst;
5082       }
5083 
5084       case Iop_Shl64x2:    op = Pav_SHL;    goto do_AvBin64x2;
5085       case Iop_Shr64x2:    op = Pav_SHR;    goto do_AvBin64x2;
5086       case Iop_Sar64x2:    op = Pav_SAR;    goto do_AvBin64x2;
5087       case Iop_Rol64x2:    op = Pav_ROTL;   goto do_AvBin64x2;
5088       case Iop_NarrowBin64to32x4:    op = Pav_PACKUU;  goto do_AvBin64x2;
5089       case Iop_QNarrowBin64Sto32Sx4: op = Pav_QPACKSS; goto do_AvBin64x2;
5090       case Iop_QNarrowBin64Uto32Ux4: op = Pav_QPACKUU; goto do_AvBin64x2;
5091       case Iop_InterleaveHI64x2:  op = Pav_MRGHI;  goto do_AvBin64x2;
5092       case Iop_InterleaveLO64x2:  op = Pav_MRGLO;  goto do_AvBin64x2;
5093       case Iop_Add64x2:    op = Pav_ADDU;   goto do_AvBin64x2;
5094       case Iop_Sub64x2:    op = Pav_SUBU;   goto do_AvBin64x2;
5095       case Iop_Max64Ux2:   op = Pav_MAXU;   goto do_AvBin64x2;
5096       case Iop_Max64Sx2:   op = Pav_MAXS;   goto do_AvBin64x2;
5097       case Iop_Min64Ux2:   op = Pav_MINU;   goto do_AvBin64x2;
5098       case Iop_Min64Sx2:   op = Pav_MINS;   goto do_AvBin64x2;
5099       case Iop_CmpEQ64x2:  op = Pav_CMPEQU; goto do_AvBin64x2;
5100       case Iop_CmpGT64Ux2: op = Pav_CMPGTU; goto do_AvBin64x2;
5101       case Iop_CmpGT64Sx2: op = Pav_CMPGTS; goto do_AvBin64x2;
5102       case Iop_PolynomialMulAdd64x2: op = Pav_POLYMULADD; goto do_AvBin64x2;
5103       do_AvBin64x2: {
5104          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
5105          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
5106          HReg dst  = newVRegV(env);
5107          addInstr(env, PPCInstr_AvBin64x2(op, dst, arg1, arg2));
5108          return dst;
5109       }
5110 
5111       case Iop_ShlN8x16: op = Pav_SHL; goto do_AvShift8x16;
5112       case Iop_SarN8x16: op = Pav_SAR; goto do_AvShift8x16;
5113       do_AvShift8x16: {
5114          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
5115          HReg dst    = newVRegV(env);
5116          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
5117          addInstr(env, PPCInstr_AvBin8x16(op, dst, r_src, v_shft));
5118          return dst;
5119       }
5120 
5121       case Iop_ShlN16x8: op = Pav_SHL; goto do_AvShift16x8;
5122       case Iop_ShrN16x8: op = Pav_SHR; goto do_AvShift16x8;
5123       case Iop_SarN16x8: op = Pav_SAR; goto do_AvShift16x8;
5124       do_AvShift16x8: {
5125          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
5126          HReg dst    = newVRegV(env);
5127          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
5128          addInstr(env, PPCInstr_AvBin16x8(op, dst, r_src, v_shft));
5129          return dst;
5130       }
5131 
5132       case Iop_ShlN32x4: op = Pav_SHL; goto do_AvShift32x4;
5133       case Iop_ShrN32x4: op = Pav_SHR; goto do_AvShift32x4;
5134       case Iop_SarN32x4: op = Pav_SAR; goto do_AvShift32x4;
5135       do_AvShift32x4: {
5136          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
5137          HReg dst    = newVRegV(env);
5138          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
5139          addInstr(env, PPCInstr_AvBin32x4(op, dst, r_src, v_shft));
5140          return dst;
5141       }
5142 
5143       case Iop_ShlN64x2: op = Pav_SHL; goto do_AvShift64x2;
5144       case Iop_ShrN64x2: op = Pav_SHR; goto do_AvShift64x2;
5145       case Iop_SarN64x2: op = Pav_SAR; goto do_AvShift64x2;
5146       do_AvShift64x2: {
5147          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
5148          HReg dst    = newVRegV(env);
5149          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
5150          addInstr(env, PPCInstr_AvBin64x2(op, dst, r_src, v_shft));
5151          return dst;
5152       }
5153 
5154       case Iop_ShrV128: op = Pav_SHR; goto do_AvShiftV128;
5155       case Iop_ShlV128: op = Pav_SHL; goto do_AvShiftV128;
5156       do_AvShiftV128: {
5157          HReg dst    = newVRegV(env);
5158          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1);
5159          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2);
5160          /* Note: shift value gets masked by 127 */
5161          addInstr(env, PPCInstr_AvBinary(op, dst, r_src, v_shft));
5162          return dst;
5163       }
5164 
5165       case Iop_Perm8x16: {
5166          HReg dst   = newVRegV(env);
5167          HReg v_src = iselVecExpr(env, e->Iex.Binop.arg1);
5168          HReg v_ctl = iselVecExpr(env, e->Iex.Binop.arg2);
5169          addInstr(env, PPCInstr_AvPerm(dst, v_src, v_src, v_ctl));
5170          return dst;
5171       }
5172 
5173       case Iop_CipherV128:  op = Pav_CIPHERV128;   goto do_AvCipherV128;
5174       case Iop_CipherLV128: op = Pav_CIPHERLV128;  goto do_AvCipherV128;
5175       case Iop_NCipherV128: op = Pav_NCIPHERV128;  goto do_AvCipherV128;
5176       case Iop_NCipherLV128:op = Pav_NCIPHERLV128; goto do_AvCipherV128;
5177       do_AvCipherV128: {
5178          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
5179          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
5180          HReg dst  = newVRegV(env);
5181          addInstr(env, PPCInstr_AvCipherV128Binary(op, dst, arg1, arg2));
5182          return dst;
5183       }
5184 
5185       case Iop_SHA256:op = Pav_SHA256; goto do_AvHashV128;
5186       case Iop_SHA512:op = Pav_SHA512; goto do_AvHashV128;
5187       do_AvHashV128: {
5188          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
5189          HReg dst  = newVRegV(env);
5190          PPCRI* s_field = iselWordExpr_RI(env, e->Iex.Binop.arg2);
5191          addInstr(env, PPCInstr_AvHashV128Binary(op, dst, arg1, s_field));
5192          return dst;
5193       }
5194       default:
5195          break;
5196       } /* switch (e->Iex.Binop.op) */
5197    } /* if (e->tag == Iex_Binop) */
5198 
5199    if (e->tag == Iex_Triop) {
5200       IRTriop *triop = e->Iex.Triop.details;
5201       switch (triop->op) {
5202       case Iop_BCDAdd:op = Pav_BCDAdd; goto do_AvBCDV128;
5203       case Iop_BCDSub:op = Pav_BCDSub; goto do_AvBCDV128;
5204       do_AvBCDV128: {
5205          HReg arg1 = iselVecExpr(env, triop->arg1);
5206          HReg arg2 = iselVecExpr(env, triop->arg2);
5207          HReg dst  = newVRegV(env);
5208          PPCRI* ps = iselWordExpr_RI(env, triop->arg3);
5209          addInstr(env, PPCInstr_AvBCDV128Trinary(op, dst, arg1, arg2, ps));
5210          return dst;
5211       }
5212 
5213       case Iop_Add32Fx4: fpop = Pavfp_ADDF; goto do_32Fx4_with_rm;
5214       case Iop_Sub32Fx4: fpop = Pavfp_SUBF; goto do_32Fx4_with_rm;
5215       case Iop_Mul32Fx4: fpop = Pavfp_MULF; goto do_32Fx4_with_rm;
5216       do_32Fx4_with_rm:
5217       {
5218          HReg argL = iselVecExpr(env, triop->arg2);
5219          HReg argR = iselVecExpr(env, triop->arg3);
5220          HReg dst  = newVRegV(env);
5221          /* FIXME: this is bogus, in the sense that Altivec ignores
5222             FPSCR.RM, at least for some FP operations.  So setting the
5223             RM is pointless.  This is only really correct in the case
5224             where the RM is known, at JIT time, to be Irrm_NEAREST,
5225             since -- at least for Altivec FP add/sub/mul -- the
5226             emitted insn is hardwired to round to nearest. */
5227          set_FPU_rounding_mode(env, triop->arg1);
5228          addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
5229          return dst;
5230       }
5231 
5232       default:
5233          break;
5234       } /* switch (e->Iex.Triop.op) */
5235    } /* if (e->tag == Iex_Trinop) */
5236 
5237 
5238    if (e->tag == Iex_Const ) {
5239       vassert(e->Iex.Const.con->tag == Ico_V128);
5240       if (e->Iex.Const.con->Ico.V128 == 0x0000) {
5241          return generate_zeroes_V128(env);
5242       }
5243       else if (e->Iex.Const.con->Ico.V128 == 0xffff) {
5244          return generate_ones_V128(env);
5245       }
5246    }
5247 
5248    vex_printf("iselVecExpr(ppc) (subarch = %s): can't reduce\n",
5249               LibVEX_ppVexHwCaps(mode64 ? VexArchPPC64 : VexArchPPC32,
5250                                  env->hwcaps));
5251    ppIRExpr(e);
5252    vpanic("iselVecExpr_wrk(ppc)");
5253 }
5254 
5255 
5256 /*---------------------------------------------------------*/
5257 /*--- ISEL: Statements                                  ---*/
5258 /*---------------------------------------------------------*/
5259 
iselStmt(ISelEnv * env,IRStmt * stmt)5260 static void iselStmt ( ISelEnv* env, IRStmt* stmt )
5261 {
5262    Bool mode64 = env->mode64;
5263    if (vex_traceflags & VEX_TRACE_VCODE) {
5264       vex_printf("\n -- ");
5265       ppIRStmt(stmt);
5266       vex_printf("\n");
5267    }
5268 
5269    switch (stmt->tag) {
5270 
5271    /* --------- STORE --------- */
5272    case Ist_Store: {
5273       IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
5274       IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
5275       IREndness end   = stmt->Ist.Store.end;
5276 
5277       if (end != Iend_BE)
5278          goto stmt_fail;
5279       if (!mode64 && (tya != Ity_I32))
5280          goto stmt_fail;
5281       if (mode64 && (tya != Ity_I64))
5282          goto stmt_fail;
5283 
5284       if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
5285           (mode64 && (tyd == Ity_I64))) {
5286          PPCAMode* am_addr
5287             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
5288          HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
5289          addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(tyd)),
5290                                        am_addr, r_src, mode64 ));
5291          return;
5292       }
5293       if (tyd == Ity_F64) {
5294          PPCAMode* am_addr
5295             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
5296          HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data);
5297          addInstr(env,
5298                   PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
5299          return;
5300       }
5301       if (tyd == Ity_F32) {
5302          PPCAMode* am_addr
5303             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
5304          HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
5305          addInstr(env,
5306                   PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
5307          return;
5308       }
5309       if (tyd == Ity_D64) {
5310          PPCAMode* am_addr
5311             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
5312          HReg fr_src = iselDfp64Expr(env, stmt->Ist.Store.data);
5313          addInstr(env,
5314                   PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
5315          return;
5316       }
5317       if (tyd == Ity_D32) {
5318          PPCAMode* am_addr
5319             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
5320          HReg fr_src = iselDfp32Expr(env, stmt->Ist.Store.data);
5321          addInstr(env,
5322                   PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
5323          return;
5324       }
5325       if (tyd == Ity_V128) {
5326          PPCAMode* am_addr
5327             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
5328          HReg v_src = iselVecExpr(env, stmt->Ist.Store.data);
5329          addInstr(env,
5330                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
5331          return;
5332       }
5333       if (tyd == Ity_I64 && !mode64) {
5334          /* Just calculate the address in the register.  Life is too
5335             short to arse around trying and possibly failing to adjust
5336             the offset in a 'reg+offset' style amode. */
5337          HReg rHi32, rLo32;
5338          HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
5339          iselInt64Expr( &rHi32, &rLo32, env, stmt->Ist.Store.data );
5340          addInstr(env, PPCInstr_Store( 4/*byte-store*/,
5341                                        PPCAMode_IR( 0, r_addr ),
5342                                        rHi32,
5343                                        False/*32-bit insn please*/) );
5344          addInstr(env, PPCInstr_Store( 4/*byte-store*/,
5345                                        PPCAMode_IR( 4, r_addr ),
5346                                        rLo32,
5347                                        False/*32-bit insn please*/) );
5348          return;
5349       }
5350       break;
5351    }
5352 
5353    /* --------- PUT --------- */
5354    case Ist_Put: {
5355       IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
5356       if (ty == Ity_I8  || ty == Ity_I16 ||
5357           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
5358          HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
5359          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
5360                                           GuestStatePtr(mode64) );
5361          addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(ty)),
5362                                        am_addr, r_src, mode64 ));
5363          return;
5364       }
5365       if (!mode64 && ty == Ity_I64) {
5366          HReg rHi, rLo;
5367          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
5368                                            GuestStatePtr(mode64) );
5369          PPCAMode* am_addr4 = advance4(env, am_addr);
5370          iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Put.data);
5371          addInstr(env, PPCInstr_Store( 4, am_addr,  rHi, mode64 ));
5372          addInstr(env, PPCInstr_Store( 4, am_addr4, rLo, mode64 ));
5373          return;
5374      }
5375      if (ty == Ity_V128) {
5376          /* Guest state vectors are 16byte aligned,
5377             so don't need to worry here */
5378          HReg v_src = iselVecExpr(env, stmt->Ist.Put.data);
5379          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
5380                                            GuestStatePtr(mode64) );
5381          addInstr(env,
5382                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
5383          return;
5384       }
5385       if (ty == Ity_F64) {
5386          HReg fr_src = iselDblExpr(env, stmt->Ist.Put.data);
5387          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
5388                                           GuestStatePtr(mode64) );
5389          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
5390                                         fr_src, am_addr ));
5391          return;
5392       }
5393       if (ty == Ity_D32) {
5394          /* The 32-bit value is stored in a 64-bit register */
5395          HReg fr_src = iselDfp32Expr( env, stmt->Ist.Put.data );
5396          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
5397                                           GuestStatePtr(mode64) );
5398          addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8,
5399                                          fr_src, am_addr ) );
5400          return;
5401       }
5402       if (ty == Ity_D64) {
5403          HReg fr_src = iselDfp64Expr( env, stmt->Ist.Put.data );
5404          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
5405                                           GuestStatePtr(mode64) );
5406          addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8, fr_src, am_addr ) );
5407          return;
5408       }
5409       break;
5410    }
5411 
5412    /* --------- Indexed PUT --------- */
5413    case Ist_PutI: {
5414       IRPutI *puti = stmt->Ist.PutI.details;
5415 
5416       PPCAMode* dst_am
5417          = genGuestArrayOffset(
5418               env, puti->descr,
5419                    puti->ix, puti->bias );
5420       IRType ty = typeOfIRExpr(env->type_env, puti->data);
5421       if (mode64 && ty == Ity_I64) {
5422          HReg r_src = iselWordExpr_R(env, puti->data);
5423          addInstr(env, PPCInstr_Store( toUChar(8),
5424                                        dst_am, r_src, mode64 ));
5425          return;
5426       }
5427       if ((!mode64) && ty == Ity_I32) {
5428          HReg r_src = iselWordExpr_R(env, puti->data);
5429          addInstr(env, PPCInstr_Store( toUChar(4),
5430                                        dst_am, r_src, mode64 ));
5431          return;
5432       }
5433       break;
5434    }
5435 
5436    /* --------- TMP --------- */
5437    case Ist_WrTmp: {
5438       IRTemp tmp = stmt->Ist.WrTmp.tmp;
5439       IRType ty = typeOfIRTemp(env->type_env, tmp);
5440       if (ty == Ity_I8  || ty == Ity_I16 ||
5441           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
5442          HReg r_dst = lookupIRTemp(env, tmp);
5443          HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
5444          addInstr(env, mk_iMOVds_RR( r_dst, r_src ));
5445          return;
5446       }
5447       if (!mode64 && ty == Ity_I64) {
5448          HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
5449 
5450          iselInt64Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data);
5451          lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
5452          addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
5453          addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
5454          return;
5455       }
5456       if (mode64 && ty == Ity_I128) {
5457          HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
5458          iselInt128Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data);
5459          lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
5460          addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
5461          addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
5462          return;
5463       }
5464       if (!mode64 && ty == Ity_I128) {
5465          HReg r_srcHi, r_srcMedHi, r_srcMedLo, r_srcLo;
5466          HReg r_dstHi, r_dstMedHi, r_dstMedLo, r_dstLo;
5467 
5468          iselInt128Expr_to_32x4(&r_srcHi, &r_srcMedHi,
5469                                 &r_srcMedLo, &r_srcLo,
5470                                 env, stmt->Ist.WrTmp.data);
5471 
5472          lookupIRTempQuad( &r_dstHi, &r_dstMedHi, &r_dstMedLo,
5473                            &r_dstLo, env, tmp);
5474 
5475          addInstr(env, mk_iMOVds_RR(r_dstHi,    r_srcHi) );
5476          addInstr(env, mk_iMOVds_RR(r_dstMedHi, r_srcMedHi) );
5477          addInstr(env, mk_iMOVds_RR(r_dstMedLo, r_srcMedLo) );
5478          addInstr(env, mk_iMOVds_RR(r_dstLo,    r_srcLo) );
5479          return;
5480       }
5481       if (ty == Ity_I1) {
5482          PPCCondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data);
5483          HReg r_dst = lookupIRTemp(env, tmp);
5484          addInstr(env, PPCInstr_Set(cond, r_dst));
5485          return;
5486       }
5487       if (ty == Ity_F64) {
5488          HReg fr_dst = lookupIRTemp(env, tmp);
5489          HReg fr_src = iselDblExpr(env, stmt->Ist.WrTmp.data);
5490          addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
5491          return;
5492       }
5493       if (ty == Ity_F32) {
5494          HReg fr_dst = lookupIRTemp(env, tmp);
5495          HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data);
5496          addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
5497          return;
5498       }
5499       if (ty == Ity_D32) {
5500          HReg fr_dst = lookupIRTemp(env, tmp);
5501          HReg fr_src = iselDfp32Expr(env, stmt->Ist.WrTmp.data);
5502          addInstr(env, PPCInstr_Dfp64Unary(Pfp_MOV, fr_dst, fr_src));
5503          return;
5504       }
5505       if (ty == Ity_V128) {
5506          HReg v_dst = lookupIRTemp(env, tmp);
5507          HReg v_src = iselVecExpr(env, stmt->Ist.WrTmp.data);
5508          addInstr(env, PPCInstr_AvUnary(Pav_MOV, v_dst, v_src));
5509          return;
5510       }
5511       if (ty == Ity_D64) {
5512          HReg fr_dst = lookupIRTemp( env, tmp );
5513          HReg fr_src = iselDfp64Expr( env, stmt->Ist.WrTmp.data );
5514          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dst, fr_src ) );
5515          return;
5516       }
5517       if (ty == Ity_D128) {
5518          HReg fr_srcHi, fr_srcLo, fr_dstHi, fr_dstLo;
5519 	 //         lookupDfp128IRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
5520          lookupIRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
5521          iselDfp128Expr( &fr_srcHi, &fr_srcLo, env, stmt->Ist.WrTmp.data );
5522          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstHi, fr_srcHi ) );
5523          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstLo, fr_srcLo ) );
5524          return;
5525       }
5526       break;
5527    }
5528 
5529    /* --------- Load Linked or Store Conditional --------- */
5530    case Ist_LLSC: {
5531       IRTemp res    = stmt->Ist.LLSC.result;
5532       IRType tyRes  = typeOfIRTemp(env->type_env, res);
5533       IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
5534 
5535       if (stmt->Ist.LLSC.end != Iend_BE)
5536          goto stmt_fail;
5537       if (!mode64 && (tyAddr != Ity_I32))
5538          goto stmt_fail;
5539       if (mode64 && (tyAddr != Ity_I64))
5540          goto stmt_fail;
5541 
5542       if (stmt->Ist.LLSC.storedata == NULL) {
5543          /* LL */
5544          HReg r_addr = iselWordExpr_R( env, stmt->Ist.LLSC.addr );
5545          HReg r_dst  = lookupIRTemp(env, res);
5546          if (tyRes == Ity_I32) {
5547             addInstr(env, PPCInstr_LoadL( 4, r_dst, r_addr, mode64 ));
5548             return;
5549          }
5550          if (tyRes == Ity_I64 && mode64) {
5551             addInstr(env, PPCInstr_LoadL( 8, r_dst, r_addr, mode64 ));
5552             return;
5553          }
5554          /* fallthru */;
5555       } else {
5556          /* SC */
5557          HReg   r_res  = lookupIRTemp(env, res); /* :: Ity_I1 */
5558          HReg   r_a    = iselWordExpr_R(env, stmt->Ist.LLSC.addr);
5559          HReg   r_src  = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
5560          HReg   r_tmp  = newVRegI(env);
5561          IRType tyData = typeOfIRExpr(env->type_env,
5562                                       stmt->Ist.LLSC.storedata);
5563          vassert(tyRes == Ity_I1);
5564          if (tyData == Ity_I32 || (tyData == Ity_I64 && mode64)) {
5565             addInstr(env, PPCInstr_StoreC( tyData==Ity_I32 ? 4 : 8,
5566                                            r_a, r_src, mode64 ));
5567             addInstr(env, PPCInstr_MfCR( r_tmp ));
5568             addInstr(env, PPCInstr_Shft(
5569                              Pshft_SHR,
5570                              env->mode64 ? False : True
5571                                 /*F:64-bit, T:32-bit shift*/,
5572                              r_tmp, r_tmp,
5573                              PPCRH_Imm(False/*unsigned*/, 29)));
5574             /* Probably unnecessary, since the IR dest type is Ity_I1,
5575                and so we are entitled to leave whatever junk we like
5576                drifting round in the upper 31 or 63 bits of r_res.
5577                However, for the sake of conservativeness .. */
5578             addInstr(env, PPCInstr_Alu(
5579                              Palu_AND,
5580                              r_res, r_tmp,
5581                              PPCRH_Imm(False/*signed*/, 1)));
5582             return;
5583          }
5584          /* fallthru */
5585       }
5586       goto stmt_fail;
5587       /*NOTREACHED*/
5588    }
5589 
5590    /* --------- Call to DIRTY helper --------- */
5591    case Ist_Dirty: {
5592       IRDirty* d = stmt->Ist.Dirty.details;
5593 
5594       /* Figure out the return type, if any. */
5595       IRType retty = Ity_INVALID;
5596       if (d->tmp != IRTemp_INVALID)
5597          retty = typeOfIRTemp(env->type_env, d->tmp);
5598 
5599       /* Throw out any return types we don't know about. */
5600       Bool retty_ok = False;
5601       if (mode64) {
5602          switch (retty) {
5603             case Ity_INVALID: /* function doesn't return anything */
5604             case Ity_V128:
5605             case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
5606                retty_ok = True; break;
5607             default:
5608                break;
5609          }
5610       } else {
5611          switch (retty) {
5612             case Ity_INVALID: /* function doesn't return anything */
5613             case Ity_V128:
5614             case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
5615                retty_ok = True; break;
5616             default:
5617                break;
5618          }
5619       }
5620       if (!retty_ok)
5621          break; /* will go to stmt_fail: */
5622 
5623       /* Marshal args, do the call, clear stack, set the return value
5624          to 0x555..555 if this is a conditional call that returns a
5625          value and the call is skipped. */
5626       UInt   addToSp = 0;
5627       RetLoc rloc    = mk_RetLoc_INVALID();
5628       doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args );
5629       vassert(is_sane_RetLoc(rloc));
5630 
5631       /* Now figure out what to do with the returned value, if any. */
5632       switch (retty) {
5633          case Ity_INVALID: {
5634             /* No return value.  Nothing to do. */
5635             vassert(d->tmp == IRTemp_INVALID);
5636             vassert(rloc.pri == RLPri_None);
5637             vassert(addToSp == 0);
5638             return;
5639          }
5640          case Ity_I32: case Ity_I16: case Ity_I8: {
5641             /* The returned value is in %r3.  Park it in the register
5642                associated with tmp. */
5643             HReg r_dst = lookupIRTemp(env, d->tmp);
5644             addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
5645             vassert(rloc.pri == RLPri_Int);
5646             vassert(addToSp == 0);
5647             return;
5648          }
5649          case Ity_I64:
5650             if (mode64) {
5651                /* The returned value is in %r3.  Park it in the register
5652                   associated with tmp. */
5653                HReg r_dst = lookupIRTemp(env, d->tmp);
5654                addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
5655                vassert(rloc.pri == RLPri_Int);
5656                vassert(addToSp == 0);
5657             } else {
5658                /* The returned value is in %r3:%r4.  Park it in the
5659                   register-pair associated with tmp. */
5660                HReg r_dstHi = INVALID_HREG;
5661                HReg r_dstLo = INVALID_HREG;
5662                lookupIRTempPair( &r_dstHi, &r_dstLo, env, d->tmp);
5663                addInstr(env, mk_iMOVds_RR(r_dstHi, hregPPC_GPR3(mode64)));
5664                addInstr(env, mk_iMOVds_RR(r_dstLo, hregPPC_GPR4(mode64)));
5665                vassert(rloc.pri == RLPri_2Int);
5666                vassert(addToSp == 0);
5667             }
5668             return;
5669          case Ity_V128: {
5670             /* The returned value is on the stack, and *retloc tells
5671                us where.  Fish it off the stack and then move the
5672                stack pointer upwards to clear it, as directed by
5673                doHelperCall. */
5674             vassert(rloc.pri == RLPri_V128SpRel);
5675             vassert(addToSp >= 16);
5676             HReg      dst = lookupIRTemp(env, d->tmp);
5677             PPCAMode* am  = PPCAMode_IR(rloc.spOff, StackFramePtr(mode64));
5678             addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, dst, am ));
5679             add_to_sp(env, addToSp);
5680             return;
5681          }
5682          default:
5683             /*NOTREACHED*/
5684             vassert(0);
5685       }
5686    }
5687 
5688    /* --------- MEM FENCE --------- */
5689    case Ist_MBE:
5690       switch (stmt->Ist.MBE.event) {
5691          case Imbe_Fence:
5692             addInstr(env, PPCInstr_MFence());
5693             return;
5694          default:
5695             break;
5696       }
5697       break;
5698 
5699    /* --------- INSTR MARK --------- */
5700    /* Doesn't generate any executable code ... */
5701    case Ist_IMark:
5702        return;
5703 
5704    /* --------- ABI HINT --------- */
5705    /* These have no meaning (denotation in the IR) and so we ignore
5706       them ... if any actually made it this far. */
5707    case Ist_AbiHint:
5708        return;
5709 
5710    /* --------- NO-OP --------- */
5711    /* Fairly self-explanatory, wouldn't you say? */
5712    case Ist_NoOp:
5713        return;
5714 
5715    /* --------- EXIT --------- */
5716    case Ist_Exit: {
5717       IRConst* dst = stmt->Ist.Exit.dst;
5718       if (!mode64 && dst->tag != Ico_U32)
5719          vpanic("iselStmt(ppc): Ist_Exit: dst is not a 32-bit value");
5720       if (mode64 && dst->tag != Ico_U64)
5721          vpanic("iselStmt(ppc64): Ist_Exit: dst is not a 64-bit value");
5722 
5723       PPCCondCode cc    = iselCondCode(env, stmt->Ist.Exit.guard);
5724       PPCAMode*   amCIA = PPCAMode_IR(stmt->Ist.Exit.offsIP,
5725                                       hregPPC_GPR31(mode64));
5726 
5727       /* Case: boring transfer to known address */
5728       if (stmt->Ist.Exit.jk == Ijk_Boring
5729           || stmt->Ist.Exit.jk == Ijk_Call
5730           /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
5731          if (env->chainingAllowed) {
5732             /* .. almost always true .. */
5733             /* Skip the event check at the dst if this is a forwards
5734                edge. */
5735             Bool toFastEP
5736                = mode64
5737                ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
5738                : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
5739             if (0) vex_printf("%s", toFastEP ? "Y" : ",");
5740             addInstr(env, PPCInstr_XDirect(
5741                              mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
5742                                     : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
5743                              amCIA, cc, toFastEP));
5744          } else {
5745             /* .. very occasionally .. */
5746             /* We can't use chaining, so ask for an assisted transfer,
5747                as that's the only alternative that is allowable. */
5748             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
5749             addInstr(env, PPCInstr_XAssisted(r, amCIA, cc, Ijk_Boring));
5750          }
5751          return;
5752       }
5753 
5754       /* Case: assisted transfer to arbitrary address */
5755       switch (stmt->Ist.Exit.jk) {
5756          /* Keep this list in sync with that in iselNext below */
5757          case Ijk_ClientReq:
5758          case Ijk_EmFail:
5759          case Ijk_EmWarn:
5760          case Ijk_NoDecode:
5761          case Ijk_NoRedir:
5762          case Ijk_SigBUS:
5763          case Ijk_SigTRAP:
5764          case Ijk_Sys_syscall:
5765          case Ijk_InvalICache:
5766          {
5767             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
5768             addInstr(env, PPCInstr_XAssisted(r, amCIA, cc,
5769                                              stmt->Ist.Exit.jk));
5770             return;
5771          }
5772          default:
5773             break;
5774       }
5775 
5776       /* Do we ever expect to see any other kind? */
5777       goto stmt_fail;
5778    }
5779 
5780    default: break;
5781    }
5782   stmt_fail:
5783    ppIRStmt(stmt);
5784    vpanic("iselStmt(ppc)");
5785 }
5786 
5787 
5788 /*---------------------------------------------------------*/
5789 /*--- ISEL: Basic block terminators (Nexts)             ---*/
5790 /*---------------------------------------------------------*/
5791 
iselNext(ISelEnv * env,IRExpr * next,IRJumpKind jk,Int offsIP)5792 static void iselNext ( ISelEnv* env,
5793                        IRExpr* next, IRJumpKind jk, Int offsIP )
5794 {
5795    if (vex_traceflags & VEX_TRACE_VCODE) {
5796       vex_printf( "\n-- PUT(%d) = ", offsIP);
5797       ppIRExpr( next );
5798       vex_printf( "; exit-");
5799       ppIRJumpKind(jk);
5800       vex_printf( "\n");
5801    }
5802 
5803    PPCCondCode always = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
5804 
5805    /* Case: boring transfer to known address */
5806    if (next->tag == Iex_Const) {
5807       IRConst* cdst = next->Iex.Const.con;
5808       vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
5809       if (jk == Ijk_Boring || jk == Ijk_Call) {
5810          /* Boring transfer to known address */
5811          PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
5812          if (env->chainingAllowed) {
5813             /* .. almost always true .. */
5814             /* Skip the event check at the dst if this is a forwards
5815                edge. */
5816             Bool toFastEP
5817                = env->mode64
5818                ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
5819                : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
5820             if (0) vex_printf("%s", toFastEP ? "X" : ".");
5821             addInstr(env, PPCInstr_XDirect(
5822                              env->mode64 ? (Addr64)cdst->Ico.U64
5823                                          : (Addr64)cdst->Ico.U32,
5824                              amCIA, always, toFastEP));
5825          } else {
5826             /* .. very occasionally .. */
5827             /* We can't use chaining, so ask for an assisted transfer,
5828                as that's the only alternative that is allowable. */
5829             HReg r = iselWordExpr_R(env, next);
5830             addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
5831                                              Ijk_Boring));
5832          }
5833          return;
5834       }
5835    }
5836 
5837    /* Case: call/return (==boring) transfer to any address */
5838    switch (jk) {
5839       case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
5840          HReg       r     = iselWordExpr_R(env, next);
5841          PPCAMode*  amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
5842          if (env->chainingAllowed) {
5843             addInstr(env, PPCInstr_XIndir(r, amCIA, always));
5844          } else {
5845             addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
5846                                              Ijk_Boring));
5847          }
5848          return;
5849       }
5850       default:
5851          break;
5852    }
5853 
5854    /* Case: assisted transfer to arbitrary address */
5855    switch (jk) {
5856       /* Keep this list in sync with that for Ist_Exit above */
5857       case Ijk_ClientReq:
5858       case Ijk_EmFail:
5859       case Ijk_EmWarn:
5860       case Ijk_NoDecode:
5861       case Ijk_NoRedir:
5862       case Ijk_SigBUS:
5863       case Ijk_SigTRAP:
5864       case Ijk_Sys_syscall:
5865       case Ijk_InvalICache:
5866       {
5867          HReg      r     = iselWordExpr_R(env, next);
5868          PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
5869          addInstr(env, PPCInstr_XAssisted(r, amCIA, always, jk));
5870          return;
5871       }
5872       default:
5873          break;
5874    }
5875 
5876    vex_printf( "\n-- PUT(%d) = ", offsIP);
5877    ppIRExpr( next );
5878    vex_printf( "; exit-");
5879    ppIRJumpKind(jk);
5880    vex_printf( "\n");
5881    vassert(0); // are we expecting any other kind?
5882 }
5883 
5884 
5885 /*---------------------------------------------------------*/
5886 /*--- Insn selector top-level                           ---*/
5887 /*---------------------------------------------------------*/
5888 
5889 /* Translate an entire SB to ppc code. */
iselSB_PPC(IRSB * bb,VexArch arch_host,VexArchInfo * archinfo_host,VexAbiInfo * vbi,Int offs_Host_EvC_Counter,Int offs_Host_EvC_FailAddr,Bool chainingAllowed,Bool addProfInc,Addr64 max_ga)5890 HInstrArray* iselSB_PPC ( IRSB* bb,
5891                           VexArch      arch_host,
5892                           VexArchInfo* archinfo_host,
5893                           VexAbiInfo*  vbi,
5894                           Int offs_Host_EvC_Counter,
5895                           Int offs_Host_EvC_FailAddr,
5896                           Bool chainingAllowed,
5897                           Bool addProfInc,
5898                           Addr64 max_ga )
5899 {
5900    Int       i, j;
5901    HReg      hregLo, hregMedLo, hregMedHi, hregHi;
5902    ISelEnv*  env;
5903    UInt      hwcaps_host = archinfo_host->hwcaps;
5904    Bool      mode64 = False;
5905    UInt      mask32, mask64;
5906    PPCAMode *amCounter, *amFailAddr;
5907 
5908 
5909    vassert(arch_host == VexArchPPC32 || arch_host == VexArchPPC64);
5910    mode64 = arch_host == VexArchPPC64;
5911    if (!mode64) vassert(max_ga <= 0xFFFFFFFFULL);
5912 
5913    /* do some sanity checks */
5914    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
5915             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
5916             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
5917 
5918 
5919    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
5920             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
5921             | VEX_HWCAPS_PPC64_ISA2_07;
5922 
5923    if (mode64) {
5924       vassert((hwcaps_host & mask32) == 0);
5925    } else {
5926       vassert((hwcaps_host & mask64) == 0);
5927    }
5928 
5929    /* Make up an initial environment to use. */
5930    env = LibVEX_Alloc(sizeof(ISelEnv));
5931    env->vreg_ctr = 0;
5932 
5933    /* Are we being ppc32 or ppc64? */
5934    env->mode64 = mode64;
5935 
5936    /* Set up output code array. */
5937    env->code = newHInstrArray();
5938 
5939    /* Copy BB's type env. */
5940    env->type_env = bb->tyenv;
5941 
5942    /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
5943     * change as we go along.
5944     *
5945     * vregmap2 and vregmap3 are only used in 32 bit mode
5946     * for supporting I128 in 32-bit mode
5947     */
5948    env->n_vregmap = bb->tyenv->types_used;
5949    env->vregmapLo    = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
5950    env->vregmapMedLo = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
5951    if (mode64) {
5952       env->vregmapMedHi = NULL;
5953       env->vregmapHi    = NULL;
5954    } else {
5955       env->vregmapMedHi = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
5956       env->vregmapHi    = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
5957    }
5958 
5959    /* and finally ... */
5960    env->chainingAllowed = chainingAllowed;
5961    env->max_ga          = max_ga;
5962    env->hwcaps          = hwcaps_host;
5963    env->previous_rm     = NULL;
5964    env->vbi             = vbi;
5965 
5966    /* For each IR temporary, allocate a suitably-kinded virtual
5967       register. */
5968    j = 0;
5969    for (i = 0; i < env->n_vregmap; i++) {
5970       hregLo = hregMedLo = hregMedHi = hregHi = INVALID_HREG;
5971       switch (bb->tyenv->types[i]) {
5972       case Ity_I1:
5973       case Ity_I8:
5974       case Ity_I16:
5975       case Ity_I32:
5976          if (mode64) { hregLo    = mkHReg(j++, HRcInt64,  True); break;
5977          } else {      hregLo    = mkHReg(j++, HRcInt32,  True); break;
5978          }
5979       case Ity_I64:
5980          if (mode64) { hregLo    = mkHReg(j++, HRcInt64,  True); break;
5981          } else {      hregLo    = mkHReg(j++, HRcInt32,  True);
5982          hregMedLo = mkHReg(j++, HRcInt32,  True); break;
5983          }
5984       case Ity_I128:
5985          if (mode64) { hregLo    = mkHReg(j++, HRcInt64,  True);
5986          hregMedLo = mkHReg(j++, HRcInt64,  True); break;
5987          } else {      hregLo    = mkHReg(j++, HRcInt32,  True);
5988          hregMedLo = mkHReg(j++, HRcInt32,  True);
5989          hregMedHi = mkHReg(j++, HRcInt32,  True);
5990          hregHi    = mkHReg(j++, HRcInt32,  True); break;
5991          }
5992       case Ity_F32:
5993       case Ity_F64:    hregLo    = mkHReg(j++, HRcFlt64,  True); break;
5994       case Ity_V128:   hregLo    = mkHReg(j++, HRcVec128, True); break;
5995       case Ity_D32:
5996       case Ity_D64:    hregLo    = mkHReg(j++, HRcFlt64,  True); break;
5997       case Ity_D128:   hregLo    = mkHReg(j++, HRcFlt64,  True);
5998       hregMedLo = mkHReg(j++, HRcFlt64,  True); break;
5999       default:
6000          ppIRType(bb->tyenv->types[i]);
6001          vpanic("iselBB(ppc): IRTemp type");
6002       }
6003       env->vregmapLo[i]    = hregLo;
6004       env->vregmapMedLo[i] = hregMedLo;
6005       if (!mode64) {
6006          env->vregmapMedHi[i] = hregMedHi;
6007          env->vregmapHi[i]    = hregHi;
6008       }
6009    }
6010    env->vreg_ctr = j;
6011 
6012    /* The very first instruction must be an event check. */
6013    amCounter  = PPCAMode_IR(offs_Host_EvC_Counter, hregPPC_GPR31(mode64));
6014    amFailAddr = PPCAMode_IR(offs_Host_EvC_FailAddr, hregPPC_GPR31(mode64));
6015    addInstr(env, PPCInstr_EvCheck(amCounter, amFailAddr));
6016 
6017    /* Possibly a block counter increment (for profiling).  At this
6018       point we don't know the address of the counter, so just pretend
6019       it is zero.  It will have to be patched later, but before this
6020       translation is used, by a call to LibVEX_patchProfCtr. */
6021    if (addProfInc) {
6022       addInstr(env, PPCInstr_ProfInc());
6023    }
6024 
6025    /* Ok, finally we can iterate over the statements. */
6026    for (i = 0; i < bb->stmts_used; i++)
6027       iselStmt(env, bb->stmts[i]);
6028 
6029    iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
6030 
6031    /* record the number of vregs we used. */
6032    env->code->n_vregs = env->vreg_ctr;
6033    return env->code;
6034 }
6035 
6036 
6037 /*---------------------------------------------------------------*/
6038 /*--- end                                     host_ppc_isel.c ---*/
6039 /*---------------------------------------------------------------*/
6040