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