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