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-2013 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    Int i = u & 0xFFFF;
   2479    i <<= 16;
   2480    i >>= 16;
   2481    return toBool(u == (UInt)i);
   2482 }
   2483 
   2484 static Bool uLong_fits_in_16_bits ( ULong u )
   2485 {
   2486    /* Is u the same as the sign-extend of its lower 16 bits? */
   2487    Long i = u & 0xFFFFULL;
   2488    i <<= 48;
   2489    i >>= 48;
   2490    return toBool(u == (ULong)i);
   2491 }
   2492 
   2493 static Bool uLong_is_4_aligned ( ULong u )
   2494 {
   2495    return toBool((u & 3ULL) == 0);
   2496 }
   2497 
   2498 static Bool sane_AMode ( ISelEnv* env, PPCAMode* am )
   2499 {
   2500    Bool mode64 = env->mode64;
   2501    switch (am->tag) {
   2502    case Pam_IR:
   2503       /* Using uInt_fits_in_16_bits in 64-bit mode seems a bit bogus,
   2504          somehow, but I think it's OK. */
   2505       return toBool( hregClass(am->Pam.IR.base) == HRcGPR(mode64) &&
   2506                      hregIsVirtual(am->Pam.IR.base) &&
   2507                      uInt_fits_in_16_bits(am->Pam.IR.index) );
   2508    case Pam_RR:
   2509       return toBool( hregClass(am->Pam.RR.base) == HRcGPR(mode64) &&
   2510                      hregIsVirtual(am->Pam.RR.base) &&
   2511                      hregClass(am->Pam.RR.index) == HRcGPR(mode64) &&
   2512                      hregIsVirtual(am->Pam.RR.index) );
   2513    default:
   2514       vpanic("sane_AMode: unknown ppc amode tag");
   2515    }
   2516 }
   2517 
   2518 static
   2519 PPCAMode* iselWordExpr_AMode ( ISelEnv* env, IRExpr* e, IRType xferTy,
   2520                                IREndness IEndianess )
   2521 {
   2522    PPCAMode* am = iselWordExpr_AMode_wrk(env, e, xferTy, IEndianess);
   2523    vassert(sane_AMode(env, am));
   2524    return am;
   2525 }
   2526 
   2527 /* DO NOT CALL THIS DIRECTLY ! */
   2528 static PPCAMode* iselWordExpr_AMode_wrk ( ISelEnv* env, IRExpr* e,
   2529                                           IRType xferTy, IREndness IEndianess )
   2530 {
   2531    IRType ty = typeOfIRExpr(env->type_env,e);
   2532 
   2533    if (env->mode64) {
   2534 
   2535       /* If the data load/store type is I32 or I64, this amode might
   2536          be destined for use in ld/ldu/lwa/st/stu.  In which case
   2537          insist that if it comes out as an _IR, the immediate must
   2538          have its bottom two bits be zero.  This does assume that for
   2539          any other type (I8/I16/I128/F32/F64/V128) the amode will not
   2540          be parked in any such instruction.  But that seems a
   2541          reasonable assumption.  */
   2542       Bool aligned4imm = toBool(xferTy == Ity_I32 || xferTy == Ity_I64);
   2543 
   2544       vassert(ty == Ity_I64);
   2545 
   2546       /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
   2547       if (e->tag == Iex_Binop
   2548           && e->Iex.Binop.op == Iop_Add64
   2549           && e->Iex.Binop.arg2->tag == Iex_Const
   2550           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
   2551           && (aligned4imm  ? uLong_is_4_aligned(e->Iex.Binop.arg2
   2552                                                  ->Iex.Const.con->Ico.U64)
   2553                            : True)
   2554           && uLong_fits_in_16_bits(e->Iex.Binop.arg2
   2555                                     ->Iex.Const.con->Ico.U64)) {
   2556          return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
   2557                              iselWordExpr_R(env, e->Iex.Binop.arg1,
   2558                                             IEndianess) );
   2559       }
   2560 
   2561       /* Add64(expr,expr) */
   2562       if (e->tag == Iex_Binop
   2563           && e->Iex.Binop.op == Iop_Add64) {
   2564          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   2565          HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
   2566          return PPCAMode_RR( r_idx, r_base );
   2567       }
   2568 
   2569    } else {
   2570 
   2571       vassert(ty == Ity_I32);
   2572 
   2573       /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
   2574       if (e->tag == Iex_Binop
   2575           && e->Iex.Binop.op == Iop_Add32
   2576           && e->Iex.Binop.arg2->tag == Iex_Const
   2577           && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
   2578           && uInt_fits_in_16_bits(e->Iex.Binop.arg2
   2579                                    ->Iex.Const.con->Ico.U32)) {
   2580          return PPCAMode_IR( (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
   2581                              iselWordExpr_R(env, e->Iex.Binop.arg1,
   2582                                             IEndianess) );
   2583       }
   2584 
   2585       /* Add32(expr,expr) */
   2586       if (e->tag == Iex_Binop
   2587           && e->Iex.Binop.op == Iop_Add32) {
   2588          HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   2589          HReg r_idx  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
   2590          return PPCAMode_RR( r_idx, r_base );
   2591       }
   2592 
   2593    }
   2594 
   2595    /* Doesn't match anything in particular.  Generate it into
   2596       a register and use that. */
   2597    return PPCAMode_IR( 0, iselWordExpr_R(env,e,IEndianess) );
   2598 }
   2599 
   2600 
   2601 /* --------------------- RH --------------------- */
   2602 
   2603 /* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
   2604    (reg-or-halfword-immediate).  It's important to specify whether the
   2605    immediate is to be regarded as signed or not.  If yes, this will
   2606    never return -32768 as an immediate; this guaranteed that all
   2607    signed immediates that are return can have their sign inverted if
   2608    need be. */
   2609 
   2610 static PPCRH* iselWordExpr_RH ( ISelEnv* env, Bool syned, IRExpr* e,
   2611                                 IREndness IEndianess )
   2612 {
   2613   PPCRH* ri = iselWordExpr_RH_wrk(env, syned, e, IEndianess);
   2614    /* sanity checks ... */
   2615    switch (ri->tag) {
   2616    case Prh_Imm:
   2617       vassert(ri->Prh.Imm.syned == syned);
   2618       if (syned)
   2619          vassert(ri->Prh.Imm.imm16 != 0x8000);
   2620       return ri;
   2621    case Prh_Reg:
   2622       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
   2623       vassert(hregIsVirtual(ri->Prh.Reg.reg));
   2624       return ri;
   2625    default:
   2626       vpanic("iselIntExpr_RH: unknown ppc RH tag");
   2627    }
   2628 }
   2629 
   2630 /* DO NOT CALL THIS DIRECTLY ! */
   2631 static PPCRH* iselWordExpr_RH_wrk ( ISelEnv* env, Bool syned, IRExpr* e,
   2632                                     IREndness IEndianess )
   2633 {
   2634    ULong u;
   2635    Long  l;
   2636    IRType ty = typeOfIRExpr(env->type_env,e);
   2637    vassert(ty == Ity_I8  || ty == Ity_I16 ||
   2638            ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
   2639 
   2640    /* special case: immediate */
   2641    if (e->tag == Iex_Const) {
   2642       IRConst* con = e->Iex.Const.con;
   2643       /* What value are we aiming to generate? */
   2644       switch (con->tag) {
   2645       /* Note: Not sign-extending - we carry 'syned' around */
   2646       case Ico_U64: vassert(env->mode64);
   2647                     u =              con->Ico.U64; break;
   2648       case Ico_U32: u = 0xFFFFFFFF & con->Ico.U32; break;
   2649       case Ico_U16: u = 0x0000FFFF & con->Ico.U16; break;
   2650       case Ico_U8:  u = 0x000000FF & con->Ico.U8; break;
   2651       default:      vpanic("iselIntExpr_RH.Iex_Const(ppch)");
   2652       }
   2653       l = (Long)u;
   2654       /* Now figure out if it's representable. */
   2655       if (!syned && u <= 65535) {
   2656          return PPCRH_Imm(False/*unsigned*/, toUShort(u & 0xFFFF));
   2657       }
   2658       if (syned && l >= -32767 && l <= 32767) {
   2659          return PPCRH_Imm(True/*signed*/, toUShort(u & 0xFFFF));
   2660       }
   2661       /* no luck; use the Slow Way. */
   2662    }
   2663 
   2664    /* default case: calculate into a register and return that */
   2665    return PPCRH_Reg( iselWordExpr_R ( env, e, IEndianess ) );
   2666 }
   2667 
   2668 
   2669 /* --------------------- RIs --------------------- */
   2670 
   2671 /* Calculate an expression into an PPCRI operand.  As with
   2672    iselIntExpr_R, the expression can have type 32, 16 or 8 bits, or,
   2673    in 64-bit mode, 64 bits. */
   2674 
   2675 static PPCRI* iselWordExpr_RI ( ISelEnv* env, IRExpr* e, IREndness IEndianess )
   2676 {
   2677    PPCRI* ri = iselWordExpr_RI_wrk(env, e, IEndianess);
   2678    /* sanity checks ... */
   2679    switch (ri->tag) {
   2680    case Pri_Imm:
   2681       return ri;
   2682    case Pri_Reg:
   2683       vassert(hregClass(ri->Pri.Reg) == HRcGPR(env->mode64));
   2684       vassert(hregIsVirtual(ri->Pri.Reg));
   2685       return ri;
   2686    default:
   2687       vpanic("iselIntExpr_RI: unknown ppc RI tag");
   2688    }
   2689 }
   2690 
   2691 /* DO NOT CALL THIS DIRECTLY ! */
   2692 static PPCRI* iselWordExpr_RI_wrk ( ISelEnv* env, IRExpr* e,
   2693                                     IREndness IEndianess )
   2694 {
   2695    Long  l;
   2696    IRType ty = typeOfIRExpr(env->type_env,e);
   2697    vassert(ty == Ity_I8  || ty == Ity_I16 ||
   2698            ty == Ity_I32 || ((ty == Ity_I64) && env->mode64));
   2699 
   2700    /* special case: immediate */
   2701    if (e->tag == Iex_Const) {
   2702       IRConst* con = e->Iex.Const.con;
   2703       switch (con->tag) {
   2704       case Ico_U64: vassert(env->mode64);
   2705                     l = (Long)            con->Ico.U64; break;
   2706       case Ico_U32: l = (Long)(Int)       con->Ico.U32; break;
   2707       case Ico_U16: l = (Long)(Int)(Short)con->Ico.U16; break;
   2708       case Ico_U8:  l = (Long)(Int)(Char )con->Ico.U8;  break;
   2709       default:      vpanic("iselIntExpr_RI.Iex_Const(ppch)");
   2710       }
   2711       return PPCRI_Imm((ULong)l);
   2712    }
   2713 
   2714    /* default case: calculate into a register and return that */
   2715    return PPCRI_Reg( iselWordExpr_R ( env, e, IEndianess ) );
   2716 }
   2717 
   2718 
   2719 /* --------------------- RH5u --------------------- */
   2720 
   2721 /* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
   2722    being an immediate in the range 1 .. 31 inclusive.  Used for doing
   2723    shift amounts.  Only used in 32-bit mode. */
   2724 
   2725 static PPCRH* iselWordExpr_RH5u ( ISelEnv* env, IRExpr* e,
   2726                                   IREndness IEndianess )
   2727 {
   2728    PPCRH* ri;
   2729    vassert(!env->mode64);
   2730    ri = iselWordExpr_RH5u_wrk(env, e, IEndianess);
   2731    /* sanity checks ... */
   2732    switch (ri->tag) {
   2733    case Prh_Imm:
   2734       vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 31);
   2735       vassert(!ri->Prh.Imm.syned);
   2736       return ri;
   2737    case Prh_Reg:
   2738       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
   2739       vassert(hregIsVirtual(ri->Prh.Reg.reg));
   2740       return ri;
   2741    default:
   2742       vpanic("iselIntExpr_RH5u: unknown ppc RI tag");
   2743    }
   2744 }
   2745 
   2746 /* DO NOT CALL THIS DIRECTLY ! */
   2747 static PPCRH* iselWordExpr_RH5u_wrk ( ISelEnv* env, IRExpr* e,
   2748                                       IREndness IEndianess )
   2749 {
   2750    IRType ty = typeOfIRExpr(env->type_env,e);
   2751    vassert(ty == Ity_I8);
   2752 
   2753    /* special case: immediate */
   2754    if (e->tag == Iex_Const
   2755        && e->Iex.Const.con->tag == Ico_U8
   2756        && e->Iex.Const.con->Ico.U8 >= 1
   2757        && e->Iex.Const.con->Ico.U8 <= 31) {
   2758       return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
   2759    }
   2760 
   2761    /* default case: calculate into a register and return that */
   2762    return PPCRH_Reg( iselWordExpr_R ( env, e, IEndianess ) );
   2763 }
   2764 
   2765 
   2766 /* --------------------- RH6u --------------------- */
   2767 
   2768 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter
   2769    being an immediate in the range 1 .. 63 inclusive.  Used for doing
   2770    shift amounts.  Only used in 64-bit mode. */
   2771 
   2772 static PPCRH* iselWordExpr_RH6u ( ISelEnv* env, IRExpr* e,
   2773                                   IREndness IEndianess )
   2774 {
   2775    PPCRH* ri;
   2776    vassert(env->mode64);
   2777    ri = iselWordExpr_RH6u_wrk(env, e, IEndianess);
   2778    /* sanity checks ... */
   2779    switch (ri->tag) {
   2780    case Prh_Imm:
   2781       vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 63);
   2782       vassert(!ri->Prh.Imm.syned);
   2783       return ri;
   2784    case Prh_Reg:
   2785       vassert(hregClass(ri->Prh.Reg.reg) == HRcGPR(env->mode64));
   2786       vassert(hregIsVirtual(ri->Prh.Reg.reg));
   2787       return ri;
   2788    default:
   2789       vpanic("iselIntExpr_RH6u: unknown ppc64 RI tag");
   2790    }
   2791 }
   2792 
   2793 /* DO NOT CALL THIS DIRECTLY ! */
   2794 static PPCRH* iselWordExpr_RH6u_wrk ( ISelEnv* env, IRExpr* e,
   2795                                       IREndness IEndianess )
   2796 {
   2797    IRType ty = typeOfIRExpr(env->type_env,e);
   2798    vassert(ty == Ity_I8);
   2799 
   2800    /* special case: immediate */
   2801    if (e->tag == Iex_Const
   2802        && e->Iex.Const.con->tag == Ico_U8
   2803        && e->Iex.Const.con->Ico.U8 >= 1
   2804        && e->Iex.Const.con->Ico.U8 <= 63) {
   2805       return PPCRH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8);
   2806    }
   2807 
   2808    /* default case: calculate into a register and return that */
   2809    return PPCRH_Reg( iselWordExpr_R ( env, e, IEndianess ) );
   2810 }
   2811 
   2812 
   2813 /* --------------------- CONDCODE --------------------- */
   2814 
   2815 /* Generate code to evaluated a bit-typed expression, returning the
   2816    condition code which would correspond when the expression would
   2817    notionally have returned 1. */
   2818 
   2819 static PPCCondCode iselCondCode ( ISelEnv* env, IRExpr* e,
   2820                                   IREndness IEndianess )
   2821 {
   2822    /* Uh, there's nothing we can sanity check here, unfortunately. */
   2823    return iselCondCode_wrk(env,e, IEndianess);
   2824 }
   2825 
   2826 /* DO NOT CALL THIS DIRECTLY ! */
   2827 static PPCCondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e,
   2828                                       IREndness IEndianess )
   2829 {
   2830    vassert(e);
   2831    vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
   2832 
   2833    /* Constant 1:Bit */
   2834    if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True) {
   2835       // Make a compare that will always be true:
   2836       HReg r_zero = newVRegI(env);
   2837       addInstr(env, PPCInstr_LI(r_zero, 0, env->mode64));
   2838       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
   2839                                  7/*cr*/, r_zero, PPCRH_Reg(r_zero)));
   2840       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
   2841    }
   2842 
   2843    /* Not1(...) */
   2844    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
   2845       /* Generate code for the arg, and negate the test condition */
   2846       PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
   2847       cond.test = invertCondTest(cond.test);
   2848       return cond;
   2849    }
   2850 
   2851    /* --- patterns rooted at: 32to1 or 64to1 --- */
   2852 
   2853    /* 32to1, 64to1 */
   2854    if (e->tag == Iex_Unop &&
   2855        (e->Iex.Unop.op == Iop_32to1 || e->Iex.Unop.op == Iop_64to1)) {
   2856       HReg src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   2857       HReg tmp = newVRegI(env);
   2858       /* could do better, probably -- andi. */
   2859       addInstr(env, PPCInstr_Alu(Palu_AND, tmp,
   2860                                  src, PPCRH_Imm(False,1)));
   2861       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
   2862                                  7/*cr*/, tmp, PPCRH_Imm(False,1)));
   2863       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
   2864    }
   2865 
   2866    /* --- patterns rooted at: CmpNEZ8 --- */
   2867 
   2868    /* CmpNEZ8(x) */
   2869    /* Note this cloned as CmpNE8(x,0) below. */
   2870    /* could do better -- andi. */
   2871    if (e->tag == Iex_Unop
   2872        && e->Iex.Unop.op == Iop_CmpNEZ8) {
   2873       HReg arg = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   2874       HReg tmp = newVRegI(env);
   2875       addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
   2876                                  PPCRH_Imm(False,0xFF)));
   2877       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
   2878                                  7/*cr*/, tmp, PPCRH_Imm(False,0)));
   2879       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
   2880    }
   2881 
   2882    /* --- patterns rooted at: CmpNEZ32 --- */
   2883 
   2884    /* CmpNEZ32(x) */
   2885    if (e->tag == Iex_Unop
   2886        && e->Iex.Unop.op == Iop_CmpNEZ32) {
   2887       HReg r1 = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   2888       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
   2889                                  7/*cr*/, r1, PPCRH_Imm(False,0)));
   2890       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
   2891    }
   2892 
   2893    /* --- patterns rooted at: Cmp*32* --- */
   2894 
   2895    /* Cmp*32*(x,y) */
   2896    if (e->tag == Iex_Binop
   2897        && (e->Iex.Binop.op == Iop_CmpEQ32
   2898            || e->Iex.Binop.op == Iop_CmpNE32
   2899            || e->Iex.Binop.op == Iop_CmpLT32S
   2900            || e->Iex.Binop.op == Iop_CmpLT32U
   2901            || e->Iex.Binop.op == Iop_CmpLE32S
   2902            || e->Iex.Binop.op == Iop_CmpLE32U)) {
   2903       Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S ||
   2904                     e->Iex.Binop.op == Iop_CmpLE32S);
   2905       HReg   r1  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   2906       PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2, IEndianess);
   2907       addInstr(env, PPCInstr_Cmp(syned, True/*32bit cmp*/,
   2908                                  7/*cr*/, r1, ri2));
   2909 
   2910       switch (e->Iex.Binop.op) {
   2911       case Iop_CmpEQ32:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
   2912       case Iop_CmpNE32:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
   2913       case Iop_CmpLT32U: case Iop_CmpLT32S:
   2914          return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
   2915       case Iop_CmpLE32U: case Iop_CmpLE32S:
   2916          return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
   2917       default: vpanic("iselCondCode(ppc): CmpXX32");
   2918       }
   2919    }
   2920 
   2921    /* --- patterns rooted at: CmpNEZ64 --- */
   2922 
   2923    /* CmpNEZ64 */
   2924    if (e->tag == Iex_Unop
   2925        && e->Iex.Unop.op == Iop_CmpNEZ64) {
   2926       if (!env->mode64) {
   2927          HReg hi, lo;
   2928          HReg tmp = newVRegI(env);
   2929          iselInt64Expr( &hi, &lo, env, e->Iex.Unop.arg, IEndianess );
   2930          addInstr(env, PPCInstr_Alu(Palu_OR, tmp, lo, PPCRH_Reg(hi)));
   2931          addInstr(env, PPCInstr_Cmp(False/*sign*/, True/*32bit cmp*/,
   2932                                     7/*cr*/, tmp,PPCRH_Imm(False,0)));
   2933          return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
   2934       } else {  // mode64
   2935          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   2936          addInstr(env, PPCInstr_Cmp(False/*sign*/, False/*64bit cmp*/,
   2937                                     7/*cr*/, r_src,PPCRH_Imm(False,0)));
   2938          return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
   2939       }
   2940    }
   2941 
   2942    /* --- patterns rooted at: Cmp*64* --- */
   2943 
   2944    /* Cmp*64*(x,y) */
   2945    if (e->tag == Iex_Binop
   2946        && (e->Iex.Binop.op == Iop_CmpEQ64
   2947            || e->Iex.Binop.op == Iop_CmpNE64
   2948            || e->Iex.Binop.op == Iop_CmpLT64S
   2949            || e->Iex.Binop.op == Iop_CmpLT64U
   2950            || e->Iex.Binop.op == Iop_CmpLE64S
   2951            || e->Iex.Binop.op == Iop_CmpLE64U)) {
   2952       Bool   syned = (e->Iex.Binop.op == Iop_CmpLT64S ||
   2953                       e->Iex.Binop.op == Iop_CmpLE64S);
   2954       HReg    r1 = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   2955       PPCRH* ri2 = iselWordExpr_RH(env, syned, e->Iex.Binop.arg2, IEndianess);
   2956       vassert(env->mode64);
   2957       addInstr(env, PPCInstr_Cmp(syned, False/*64bit cmp*/,
   2958                                  7/*cr*/, r1, ri2));
   2959 
   2960       switch (e->Iex.Binop.op) {
   2961       case Iop_CmpEQ64:  return mk_PPCCondCode( Pct_TRUE,  Pcf_7EQ );
   2962       case Iop_CmpNE64:  return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
   2963       case Iop_CmpLT64U: return mk_PPCCondCode( Pct_TRUE,  Pcf_7LT );
   2964       case Iop_CmpLE64U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
   2965       default: vpanic("iselCondCode(ppc): CmpXX64");
   2966       }
   2967    }
   2968 
   2969    /* --- patterns rooted at: CmpNE8 --- */
   2970 
   2971    /* CmpNE8(x,0) */
   2972    /* Note this is a direct copy of CmpNEZ8 above. */
   2973    /* could do better -- andi. */
   2974    if (e->tag == Iex_Binop
   2975        && e->Iex.Binop.op == Iop_CmpNE8
   2976        && isZeroU8(e->Iex.Binop.arg2)) {
   2977       HReg arg = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   2978       HReg tmp = newVRegI(env);
   2979       addInstr(env, PPCInstr_Alu(Palu_AND, tmp, arg,
   2980                                  PPCRH_Imm(False,0xFF)));
   2981       addInstr(env, PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
   2982                                  7/*cr*/, tmp, PPCRH_Imm(False,0)));
   2983       return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
   2984    }
   2985 
   2986    /* var */
   2987    if (e->tag == Iex_RdTmp) {
   2988       HReg r_src      = lookupIRTemp(env, e->Iex.RdTmp.tmp);
   2989       HReg src_masked = newVRegI(env);
   2990       addInstr(env,
   2991                PPCInstr_Alu(Palu_AND, src_masked,
   2992                             r_src, PPCRH_Imm(False,1)));
   2993       addInstr(env,
   2994                PPCInstr_Cmp(False/*unsigned*/, True/*32bit cmp*/,
   2995                             7/*cr*/, src_masked, PPCRH_Imm(False,1)));
   2996       return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
   2997    }
   2998 
   2999    vex_printf("iselCondCode(ppc): No such tag(%u)\n", e->tag);
   3000    ppIRExpr(e);
   3001    vpanic("iselCondCode(ppc)");
   3002 }
   3003 
   3004 
   3005 /*---------------------------------------------------------*/
   3006 /*--- ISEL: Integer expressions (128 bit)               ---*/
   3007 /*---------------------------------------------------------*/
   3008 
   3009 /* 64-bit mode ONLY: compute a 128-bit value into a register pair,
   3010    which is returned as the first two parameters.  As with
   3011    iselWordExpr_R, these may be either real or virtual regs; in any
   3012    case they must not be changed by subsequent code emitted by the
   3013    caller.  */
   3014 
   3015 static void iselInt128Expr ( HReg* rHi, HReg* rLo,
   3016                              ISelEnv* env, IRExpr* e, IREndness IEndianess )
   3017 {
   3018    vassert(env->mode64);
   3019    iselInt128Expr_wrk(rHi, rLo, env, e, IEndianess);
   3020 #  if 0
   3021    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
   3022 #  endif
   3023    vassert(hregClass(*rHi) == HRcGPR(env->mode64));
   3024    vassert(hregIsVirtual(*rHi));
   3025    vassert(hregClass(*rLo) == HRcGPR(env->mode64));
   3026    vassert(hregIsVirtual(*rLo));
   3027 }
   3028 
   3029 /* DO NOT CALL THIS DIRECTLY ! */
   3030 static void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
   3031                                  ISelEnv* env, IRExpr* e, IREndness IEndianess )
   3032 {
   3033    vassert(e);
   3034    vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
   3035 
   3036    /* read 128-bit IRTemp */
   3037    if (e->tag == Iex_RdTmp) {
   3038       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
   3039       return;
   3040    }
   3041 
   3042    /* --------- BINARY ops --------- */
   3043    if (e->tag == Iex_Binop) {
   3044       switch (e->Iex.Binop.op) {
   3045       /* 64 x 64 -> 128 multiply */
   3046       case Iop_MullU64:
   3047       case Iop_MullS64: {
   3048          HReg     tLo     = newVRegI(env);
   3049          HReg     tHi     = newVRegI(env);
   3050          Bool     syned   = toBool(e->Iex.Binop.op == Iop_MullS64);
   3051          HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   3052          HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
   3053          addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
   3054                                      False/*lo64*/, False/*64bit mul*/,
   3055                                      tLo, r_srcL, r_srcR));
   3056          addInstr(env, PPCInstr_MulL(syned,
   3057                                      True/*hi64*/, False/*64bit mul*/,
   3058                                      tHi, r_srcL, r_srcR));
   3059          *rHi = tHi;
   3060          *rLo = tLo;
   3061          return;
   3062       }
   3063 
   3064       /* 64HLto128(e1,e2) */
   3065       case Iop_64HLto128:
   3066          *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   3067          *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
   3068          return;
   3069       default:
   3070          break;
   3071       }
   3072    } /* if (e->tag == Iex_Binop) */
   3073 
   3074 
   3075    /* --------- UNARY ops --------- */
   3076    if (e->tag == Iex_Unop) {
   3077       switch (e->Iex.Unop.op) {
   3078       default:
   3079          break;
   3080       }
   3081    } /* if (e->tag == Iex_Unop) */
   3082 
   3083    vex_printf("iselInt128Expr(ppc64): No such tag(%u)\n", e->tag);
   3084    ppIRExpr(e);
   3085    vpanic("iselInt128Expr(ppc64)");
   3086 }
   3087 
   3088 
   3089 /*---------------------------------------------------------*/
   3090 /*--- ISEL: Integer expressions (64 bit)                ---*/
   3091 /*---------------------------------------------------------*/
   3092 
   3093 /* 32-bit mode ONLY: compute a 128-bit value into a register quad */
   3094 static void iselInt128Expr_to_32x4 ( HReg* rHi, HReg* rMedHi, HReg* rMedLo,
   3095                                      HReg* rLo, ISelEnv* env, IRExpr* e,
   3096                                      IREndness IEndianess )
   3097 {
   3098    vassert(!env->mode64);
   3099    iselInt128Expr_to_32x4_wrk(rHi, rMedHi, rMedLo, rLo, env, e, IEndianess);
   3100 #  if 0
   3101    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
   3102 #  endif
   3103    vassert(hregClass(*rHi) == HRcInt32);
   3104    vassert(hregIsVirtual(*rHi));
   3105    vassert(hregClass(*rMedHi) == HRcInt32);
   3106    vassert(hregIsVirtual(*rMedHi));
   3107    vassert(hregClass(*rMedLo) == HRcInt32);
   3108    vassert(hregIsVirtual(*rMedLo));
   3109    vassert(hregClass(*rLo) == HRcInt32);
   3110    vassert(hregIsVirtual(*rLo));
   3111 }
   3112 
   3113 static void iselInt128Expr_to_32x4_wrk ( HReg* rHi, HReg* rMedHi,
   3114                                          HReg* rMedLo, HReg* rLo,
   3115                                          ISelEnv* env, IRExpr* e,
   3116                                          IREndness IEndianess )
   3117 {
   3118    vassert(e);
   3119    vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
   3120 
   3121    /* read 128-bit IRTemp */
   3122    if (e->tag == Iex_RdTmp) {
   3123       lookupIRTempQuad( rHi, rMedHi, rMedLo, rLo, env, e->Iex.RdTmp.tmp);
   3124       return;
   3125    }
   3126 
   3127    if (e->tag == Iex_Binop) {
   3128 
   3129       IROp op_binop = e->Iex.Binop.op;
   3130       switch (op_binop) {
   3131       case Iop_64HLto128:
   3132          iselInt64Expr(rHi, rMedHi, env, e->Iex.Binop.arg1, IEndianess);
   3133          iselInt64Expr(rMedLo, rLo, env, e->Iex.Binop.arg2, IEndianess);
   3134          return;
   3135       default:
   3136          vex_printf("iselInt128Expr_to_32x4_wrk: Binop case 0x%x not found\n",
   3137                     op_binop);
   3138          break;
   3139       }
   3140    }
   3141 
   3142    vex_printf("iselInt128Expr_to_32x4_wrk: e->tag 0x%x not found\n", e->tag);
   3143    return;
   3144 }
   3145 
   3146 /* 32-bit mode ONLY: compute a 64-bit value into a register pair,
   3147    which is returned as the first two parameters.  As with
   3148    iselIntExpr_R, these may be either real or virtual regs; in any
   3149    case they must not be changed by subsequent code emitted by the
   3150    caller.  */
   3151 
   3152 static void iselInt64Expr ( HReg* rHi, HReg* rLo,
   3153                             ISelEnv* env, IRExpr* e,
   3154                             IREndness IEndianess )
   3155 {
   3156    vassert(!env->mode64);
   3157    iselInt64Expr_wrk(rHi, rLo, env, e, IEndianess);
   3158 #  if 0
   3159    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
   3160 #  endif
   3161    vassert(hregClass(*rHi) == HRcInt32);
   3162    vassert(hregIsVirtual(*rHi));
   3163    vassert(hregClass(*rLo) == HRcInt32);
   3164    vassert(hregIsVirtual(*rLo));
   3165 }
   3166 
   3167 /* DO NOT CALL THIS DIRECTLY ! */
   3168 static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
   3169                                 ISelEnv* env, IRExpr* e,
   3170                                 IREndness IEndianess )
   3171 {
   3172    vassert(e);
   3173    vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
   3174 
   3175    /* 64-bit load */
   3176    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
   3177       HReg tLo    = newVRegI(env);
   3178       HReg tHi    = newVRegI(env);
   3179       HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr, IEndianess);
   3180       vassert(!env->mode64);
   3181       addInstr(env, PPCInstr_Load( 4/*byte-load*/,
   3182                                    tHi, PPCAMode_IR( 0, r_addr ),
   3183                                    False/*32-bit insn please*/) );
   3184       addInstr(env, PPCInstr_Load( 4/*byte-load*/,
   3185                                    tLo, PPCAMode_IR( 4, r_addr ),
   3186                                    False/*32-bit insn please*/) );
   3187       *rHi = tHi;
   3188       *rLo = tLo;
   3189       return;
   3190    }
   3191 
   3192    /* 64-bit literal */
   3193    if (e->tag == Iex_Const) {
   3194       ULong w64 = e->Iex.Const.con->Ico.U64;
   3195       UInt  wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
   3196       UInt  wLo = ((UInt)w64) & 0xFFFFFFFF;
   3197       HReg  tLo = newVRegI(env);
   3198       HReg  tHi = newVRegI(env);
   3199       vassert(e->Iex.Const.con->tag == Ico_U64);
   3200       addInstr(env, PPCInstr_LI(tHi, (Long)(Int)wHi, False/*mode32*/));
   3201       addInstr(env, PPCInstr_LI(tLo, (Long)(Int)wLo, False/*mode32*/));
   3202       *rHi = tHi;
   3203       *rLo = tLo;
   3204       return;
   3205    }
   3206 
   3207    /* read 64-bit IRTemp */
   3208    if (e->tag == Iex_RdTmp) {
   3209       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
   3210       return;
   3211    }
   3212 
   3213    /* 64-bit GET */
   3214    if (e->tag == Iex_Get) {
   3215       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
   3216                                        GuestStatePtr(False/*mode32*/) );
   3217       PPCAMode* am_addr4 = advance4(env, am_addr);
   3218       HReg tLo = newVRegI(env);
   3219       HReg tHi = newVRegI(env);
   3220       addInstr(env, PPCInstr_Load( 4, tHi, am_addr,  False/*mode32*/ ));
   3221       addInstr(env, PPCInstr_Load( 4, tLo, am_addr4, False/*mode32*/ ));
   3222       *rHi = tHi;
   3223       *rLo = tLo;
   3224       return;
   3225    }
   3226 
   3227    /* 64-bit ITE */
   3228    if (e->tag == Iex_ITE) { // VFD
   3229       HReg e0Lo, e0Hi, eXLo, eXHi;
   3230       iselInt64Expr(&eXHi, &eXLo, env, e->Iex.ITE.iftrue, IEndianess);
   3231       iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.ITE.iffalse, IEndianess);
   3232       HReg tLo = newVRegI(env);
   3233       HReg tHi = newVRegI(env);
   3234       addInstr(env, mk_iMOVds_RR(tHi,e0Hi));
   3235       addInstr(env, mk_iMOVds_RR(tLo,e0Lo));
   3236       PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond, IEndianess);
   3237       addInstr(env, PPCInstr_CMov(cc,tHi,PPCRI_Reg(eXHi)));
   3238       addInstr(env, PPCInstr_CMov(cc,tLo,PPCRI_Reg(eXLo)));
   3239       *rHi = tHi;
   3240       *rLo = tLo;
   3241       return;
   3242    }
   3243 
   3244    /* --------- BINARY ops --------- */
   3245    if (e->tag == Iex_Binop) {
   3246       IROp op_binop = e->Iex.Binop.op;
   3247       switch (op_binop) {
   3248          /* 32 x 32 -> 64 multiply */
   3249          case Iop_MullU32:
   3250          case Iop_MullS32: {
   3251             HReg     tLo     = newVRegI(env);
   3252             HReg     tHi     = newVRegI(env);
   3253             Bool     syned   = toBool(op_binop == Iop_MullS32);
   3254             HReg     r_srcL  = iselWordExpr_R(env, e->Iex.Binop.arg1,
   3255                                               IEndianess);
   3256             HReg     r_srcR  = iselWordExpr_R(env, e->Iex.Binop.arg2,
   3257                                               IEndianess);
   3258             addInstr(env, PPCInstr_MulL(False/*signedness irrelevant*/,
   3259                                         False/*lo32*/, True/*32bit mul*/,
   3260                                         tLo, r_srcL, r_srcR));
   3261             addInstr(env, PPCInstr_MulL(syned,
   3262                                         True/*hi32*/, True/*32bit mul*/,
   3263                                         tHi, r_srcL, r_srcR));
   3264             *rHi = tHi;
   3265             *rLo = tLo;
   3266             return;
   3267          }
   3268 
   3269          /* Or64/And64/Xor64 */
   3270          case Iop_Or64:
   3271          case Iop_And64:
   3272          case Iop_Xor64: {
   3273             HReg xLo, xHi, yLo, yHi;
   3274             HReg tLo = newVRegI(env);
   3275             HReg tHi = newVRegI(env);
   3276             PPCAluOp op = (op_binop == Iop_Or64) ? Palu_OR :
   3277                           (op_binop == Iop_And64) ? Palu_AND : Palu_XOR;
   3278             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1, IEndianess);
   3279             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2, IEndianess);
   3280             addInstr(env, PPCInstr_Alu(op, tHi, xHi, PPCRH_Reg(yHi)));
   3281             addInstr(env, PPCInstr_Alu(op, tLo, xLo, PPCRH_Reg(yLo)));
   3282             *rHi = tHi;
   3283             *rLo = tLo;
   3284             return;
   3285          }
   3286 
   3287          /* Add64 */
   3288          case Iop_Add64: {
   3289             HReg xLo, xHi, yLo, yHi;
   3290             HReg tLo = newVRegI(env);
   3291             HReg tHi = newVRegI(env);
   3292             iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1, IEndianess);
   3293             iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2, IEndianess);
   3294             addInstr(env, PPCInstr_AddSubC( True/*add*/, True /*set carry*/,
   3295                                             tLo, xLo, yLo));
   3296             addInstr(env, PPCInstr_AddSubC( True/*add*/, False/*read carry*/,
   3297                                             tHi, xHi, yHi));
   3298             *rHi = tHi;
   3299             *rLo = tLo;
   3300             return;
   3301          }
   3302 
   3303          /* 32HLto64(e1,e2) */
   3304          case Iop_32HLto64:
   3305             *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   3306             *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
   3307             return;
   3308 
   3309          /* F64toI64[S|U] */
   3310          case Iop_F64toI64S: case Iop_F64toI64U: {
   3311             HReg      tLo     = newVRegI(env);
   3312             HReg      tHi     = newVRegI(env);
   3313             HReg      r1      = StackFramePtr(env->mode64);
   3314             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
   3315             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
   3316             HReg      fsrc    = iselDblExpr(env, e->Iex.Binop.arg2,
   3317                                             IEndianess);
   3318             HReg      ftmp    = newVRegF(env);
   3319 
   3320             vassert(!env->mode64);
   3321             /* Set host rounding mode */
   3322             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   3323 
   3324             sub_from_sp( env, 16 );
   3325             addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/,
   3326                                           (op_binop == Iop_F64toI64S) ? True : False,
   3327                                           True, ftmp, fsrc));
   3328             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
   3329             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
   3330             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
   3331             add_to_sp( env, 16 );
   3332 
   3333             ///* Restore default FPU rounding. */
   3334             //set_FPU_rounding_default( env );
   3335             *rHi = tHi;
   3336             *rLo = tLo;
   3337             return;
   3338          }
   3339          case Iop_D64toI64S: {
   3340             HReg      tLo     = newVRegI(env);
   3341             HReg      tHi     = newVRegI(env);
   3342             HReg      r1      = StackFramePtr(env->mode64);
   3343             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
   3344             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
   3345             HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
   3346             HReg tmp    = newVRegF(env);
   3347 
   3348             vassert(!env->mode64);
   3349             set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   3350             addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTFIX, tmp, fr_src));
   3351 
   3352             sub_from_sp( env, 16 );
   3353             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
   3354             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
   3355             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
   3356             add_to_sp( env, 16 );
   3357             *rHi = tHi;
   3358             *rLo = tLo;
   3359             return;
   3360          }
   3361          case Iop_D128toI64S: {
   3362             PPCFpOp fpop = Pfp_DCTFIXQ;
   3363             HReg r_srcHi = newVRegF(env);
   3364             HReg r_srcLo = newVRegF(env);
   3365             HReg tLo     = newVRegI(env);
   3366             HReg tHi     = newVRegI(env);
   3367             HReg ftmp    = newVRegF(env);
   3368             PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   3369             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
   3370 
   3371             set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   3372             iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
   3373                            IEndianess);
   3374             addInstr(env, PPCInstr_DfpD128toD64(fpop, ftmp, r_srcHi, r_srcLo));
   3375 
   3376             // put the D64 result into an integer register pair
   3377             sub_from_sp( env, 16 );
   3378             addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1));
   3379             addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
   3380             addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
   3381             add_to_sp( env, 16 );
   3382             *rHi = tHi;
   3383             *rLo = tLo;
   3384             return;
   3385          }
   3386          default:
   3387             break;
   3388       }
   3389    } /* if (e->tag == Iex_Binop) */
   3390 
   3391 
   3392    /* --------- UNARY ops --------- */
   3393    if (e->tag == Iex_Unop) {
   3394       switch (e->Iex.Unop.op) {
   3395 
   3396       /* CmpwNEZ64(e) */
   3397       case Iop_CmpwNEZ64: {
   3398          HReg argHi, argLo;
   3399          HReg tmp1  = newVRegI(env);
   3400          HReg tmp2  = newVRegI(env);
   3401          iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg, IEndianess);
   3402          /* tmp1 = argHi | argLo */
   3403          addInstr(env, PPCInstr_Alu(Palu_OR, tmp1, argHi, PPCRH_Reg(argLo)));
   3404          /* tmp2 = (tmp1 | -tmp1) >>s 31 */
   3405          addInstr(env, PPCInstr_Unary(Pun_NEG,tmp2,tmp1));
   3406          addInstr(env, PPCInstr_Alu(Palu_OR, tmp2, tmp2, PPCRH_Reg(tmp1)));
   3407          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
   3408                                      tmp2, tmp2, PPCRH_Imm(False, 31)));
   3409          *rHi = tmp2;
   3410          *rLo = tmp2; /* yes, really tmp2 */
   3411          return;
   3412       }
   3413 
   3414       /* Left64 */
   3415       case Iop_Left64: {
   3416          HReg argHi, argLo;
   3417          HReg zero32 = newVRegI(env);
   3418          HReg resHi  = newVRegI(env);
   3419          HReg resLo  = newVRegI(env);
   3420          iselInt64Expr(&argHi, &argLo, env, e->Iex.Unop.arg, IEndianess);
   3421          vassert(env->mode64 == False);
   3422          addInstr(env, PPCInstr_LI(zero32, 0, env->mode64));
   3423          /* resHi:resLo = - argHi:argLo */
   3424          addInstr(env, PPCInstr_AddSubC( False/*sub*/, True/*set carry*/,
   3425                                          resLo, zero32, argLo ));
   3426          addInstr(env, PPCInstr_AddSubC( False/*sub*/, False/*read carry*/,
   3427                                          resHi, zero32, argHi ));
   3428          /* resHi:resLo |= srcHi:srcLo */
   3429          addInstr(env, PPCInstr_Alu(Palu_OR, resLo, resLo, PPCRH_Reg(argLo)));
   3430          addInstr(env, PPCInstr_Alu(Palu_OR, resHi, resHi, PPCRH_Reg(argHi)));
   3431          *rHi = resHi;
   3432          *rLo = resLo;
   3433          return;
   3434       }
   3435 
   3436       /* 32Sto64(e) */
   3437       case Iop_32Sto64: {
   3438          HReg tHi = newVRegI(env);
   3439          HReg src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   3440          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
   3441                                      tHi, src, PPCRH_Imm(False,31)));
   3442          *rHi = tHi;
   3443          *rLo = src;
   3444          return;
   3445       }
   3446       case Iop_ExtractExpD64: {
   3447          HReg tmp    = newVRegF(env);
   3448          HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
   3449          HReg      tLo     = newVRegI(env);
   3450          HReg      tHi     = newVRegI(env);
   3451          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   3452          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
   3453 
   3454          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DXEX, tmp, fr_src));
   3455 
   3456          // put the D64 result into a integer register pair
   3457          sub_from_sp( env, 16 );
   3458          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
   3459          addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
   3460          addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
   3461          add_to_sp( env, 16 );
   3462          *rHi = tHi;
   3463          *rLo = tLo;
   3464          return;
   3465       }
   3466       case Iop_ExtractExpD128: {
   3467          HReg      r_srcHi;
   3468          HReg      r_srcLo;
   3469          HReg      tmp     = newVRegF(env);
   3470          HReg      tLo     = newVRegI(env);
   3471          HReg      tHi     = newVRegI(env);
   3472          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   3473          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
   3474 
   3475          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Unop.arg, IEndianess);
   3476          addInstr(env, PPCInstr_ExtractExpD128(Pfp_DXEXQ, tmp,
   3477                                                   r_srcHi, r_srcLo));
   3478 
   3479          // put the D64 result into a integer register pair
   3480          sub_from_sp( env, 16 );
   3481          addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, tmp, zero_r1));
   3482          addInstr(env, PPCInstr_Load(4, tHi, zero_r1, False/*mode32*/));
   3483          addInstr(env, PPCInstr_Load(4, tLo, four_r1, False/*mode32*/));
   3484          add_to_sp( env, 16 );
   3485          *rHi = tHi;
   3486          *rLo = tLo;
   3487          return;
   3488       }
   3489 
   3490       /* 32Uto64(e) */
   3491       case Iop_32Uto64: {
   3492          HReg tHi = newVRegI(env);
   3493          HReg tLo = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   3494          addInstr(env, PPCInstr_LI(tHi, 0, False/*mode32*/));
   3495          *rHi = tHi;
   3496          *rLo = tLo;
   3497          return;
   3498       }
   3499 
   3500       case Iop_128to64: {
   3501          /* Narrow, return the low 64-bit half as a 32-bit
   3502           * register pair */
   3503          HReg r_Hi    = INVALID_HREG;
   3504          HReg r_MedHi = INVALID_HREG;
   3505          HReg r_MedLo = INVALID_HREG;
   3506          HReg r_Lo    = INVALID_HREG;
   3507 
   3508          iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
   3509                                 env, e->Iex.Unop.arg, IEndianess);
   3510          *rHi = r_MedLo;
   3511          *rLo = r_Lo;
   3512          return;
   3513       }
   3514 
   3515       case Iop_128HIto64: {
   3516          /* Narrow, return the high 64-bit half as a 32-bit
   3517           *  register pair */
   3518          HReg r_Hi    = INVALID_HREG;
   3519          HReg r_MedHi = INVALID_HREG;
   3520          HReg r_MedLo = INVALID_HREG;
   3521          HReg r_Lo    = INVALID_HREG;
   3522 
   3523          iselInt128Expr_to_32x4(&r_Hi, &r_MedHi, &r_MedLo, &r_Lo,
   3524                                 env, e->Iex.Unop.arg, IEndianess);
   3525          *rHi = r_Hi;
   3526          *rLo = r_MedHi;
   3527          return;
   3528       }
   3529 
   3530       /* V128{HI}to64 */
   3531       case Iop_V128HIto64:
   3532       case Iop_V128to64: {
   3533          HReg r_aligned16;
   3534          Int  off = e->Iex.Unop.op==Iop_V128HIto64 ? 0 : 8;
   3535          HReg tLo = newVRegI(env);
   3536          HReg tHi = newVRegI(env);
   3537          HReg vec = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
   3538          PPCAMode *am_off0, *am_offLO, *am_offHI;
   3539          sub_from_sp( env, 32 );     // Move SP down 32 bytes
   3540 
   3541          // get a quadword aligned address within our stack space
   3542          r_aligned16 = get_sp_aligned16( env );
   3543          am_off0  = PPCAMode_IR( 0,     r_aligned16 );
   3544          am_offHI = PPCAMode_IR( off,   r_aligned16 );
   3545          am_offLO = PPCAMode_IR( off+4, r_aligned16 );
   3546 
   3547          // store as Vec128
   3548          addInstr(env,
   3549                   PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 ));
   3550 
   3551          // load hi,lo words (of hi/lo half of vec) as Ity_I32's
   3552          addInstr(env,
   3553                   PPCInstr_Load( 4, tHi, am_offHI, False/*mode32*/ ));
   3554          addInstr(env,
   3555                   PPCInstr_Load( 4, tLo, am_offLO, False/*mode32*/ ));
   3556 
   3557          add_to_sp( env, 32 );       // Reset SP
   3558          *rHi = tHi;
   3559          *rLo = tLo;
   3560          return;
   3561       }
   3562 
   3563       /* could do better than this, but for now ... */
   3564       case Iop_1Sto64: {
   3565          HReg tLo = newVRegI(env);
   3566          HReg tHi = newVRegI(env);
   3567          PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg, IEndianess);
   3568          addInstr(env, PPCInstr_Set(cond,tLo));
   3569          addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/,
   3570                                      tLo, tLo, PPCRH_Imm(False,31)));
   3571          addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/,
   3572                                      tLo, tLo, PPCRH_Imm(False,31)));
   3573          addInstr(env, mk_iMOVds_RR(tHi, tLo));
   3574          *rHi = tHi;
   3575          *rLo = tLo;
   3576          return;
   3577       }
   3578 
   3579       case Iop_Not64: {
   3580          HReg xLo, xHi;
   3581          HReg tmpLo = newVRegI(env);
   3582          HReg tmpHi = newVRegI(env);
   3583          iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg, IEndianess);
   3584          addInstr(env, PPCInstr_Unary(Pun_NOT,tmpLo,xLo));
   3585          addInstr(env, PPCInstr_Unary(Pun_NOT,tmpHi,xHi));
   3586          *rHi = tmpHi;
   3587          *rLo = tmpLo;
   3588          return;
   3589       }
   3590 
   3591       /* ReinterpF64asI64(e) */
   3592       /* Given an IEEE754 double, produce an I64 with the same bit
   3593          pattern. */
   3594       case Iop_ReinterpF64asI64: {
   3595          PPCAMode *am_addr0, *am_addr1;
   3596          HReg fr_src  = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
   3597          HReg r_dstLo = newVRegI(env);
   3598          HReg r_dstHi = newVRegI(env);
   3599 
   3600          sub_from_sp( env, 16 );     // Move SP down 16 bytes
   3601          am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
   3602          am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
   3603 
   3604          // store as F64
   3605          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
   3606                                         fr_src, am_addr0 ));
   3607 
   3608          // load hi,lo as Ity_I32's
   3609          addInstr(env, PPCInstr_Load( 4, r_dstHi,
   3610                                       am_addr0, False/*mode32*/ ));
   3611          addInstr(env, PPCInstr_Load( 4, r_dstLo,
   3612                                       am_addr1, False/*mode32*/ ));
   3613          *rHi = r_dstHi;
   3614          *rLo = r_dstLo;
   3615 
   3616          add_to_sp( env, 16 );       // Reset SP
   3617          return;
   3618       }
   3619 
   3620       case Iop_ReinterpD64asI64: {
   3621          HReg fr_src  = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
   3622          PPCAMode *am_addr0, *am_addr1;
   3623          HReg r_dstLo = newVRegI(env);
   3624          HReg r_dstHi = newVRegI(env);
   3625 
   3626 
   3627          sub_from_sp( env, 16 );     // Move SP down 16 bytes
   3628          am_addr0 = PPCAMode_IR( 0, StackFramePtr(False/*mode32*/) );
   3629          am_addr1 = PPCAMode_IR( 4, StackFramePtr(False/*mode32*/) );
   3630 
   3631          // store as D64
   3632          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
   3633                                         fr_src, am_addr0 ));
   3634 
   3635          // load hi,lo as Ity_I32's
   3636          addInstr(env, PPCInstr_Load( 4, r_dstHi,
   3637                                       am_addr0, False/*mode32*/ ));
   3638          addInstr(env, PPCInstr_Load( 4, r_dstLo,
   3639                                       am_addr1, False/*mode32*/ ));
   3640          *rHi = r_dstHi;
   3641          *rLo = r_dstLo;
   3642 
   3643          add_to_sp( env, 16 );       // Reset SP
   3644 
   3645          return;
   3646       }
   3647 
   3648       case Iop_BCDtoDPB: {
   3649          PPCCondCode cc;
   3650          UInt        argiregs;
   3651          HReg        argregs[2];
   3652          Int         argreg;
   3653          HReg        tLo = newVRegI(env);
   3654          HReg        tHi = newVRegI(env);
   3655          HReg        tmpHi;
   3656          HReg        tmpLo;
   3657          Bool        mode64 = env->mode64;
   3658 
   3659          argregs[0] = hregPPC_GPR3(mode64);
   3660          argregs[1] = hregPPC_GPR4(mode64);
   3661 
   3662          argiregs = 0;
   3663          argreg = 0;
   3664 
   3665          iselInt64Expr( &tmpHi, &tmpLo, env, e->Iex.Unop.arg, IEndianess );
   3666 
   3667          argiregs |= ( 1 << (argreg+3 ) );
   3668          addInstr( env, mk_iMOVds_RR( argregs[argreg++], tmpHi ) );
   3669 
   3670          argiregs |= ( 1 << (argreg+3 ) );
   3671          addInstr( env, mk_iMOVds_RR( argregs[argreg], tmpLo ) );
   3672 
   3673          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
   3674 
   3675          if (IEndianess == Iend_LE) {
   3676              addInstr( env, PPCInstr_Call( cc, (Addr)h_calc_BCDtoDPB,
   3677                                            argiregs,
   3678                                            mk_RetLoc_simple(RLPri_2Int) ) );
   3679          } else {
   3680              Addr64 target;
   3681              target = mode64 ? (Addr)h_calc_BCDtoDPB :
   3682                toUInt( (Addr)h_calc_BCDtoDPB );
   3683              addInstr( env, PPCInstr_Call( cc, target,
   3684                                            argiregs,
   3685                                            mk_RetLoc_simple(RLPri_2Int) ) );
   3686          }
   3687 
   3688          addInstr( env, mk_iMOVds_RR( tHi, argregs[argreg-1] ) );
   3689          addInstr( env, mk_iMOVds_RR( tLo, argregs[argreg] ) );
   3690 
   3691          *rHi = tHi;
   3692          *rLo = tLo;
   3693          return;
   3694       }
   3695 
   3696       case Iop_DPBtoBCD: {
   3697          PPCCondCode cc;
   3698          UInt        argiregs;
   3699          HReg        argregs[2];
   3700          Int         argreg;
   3701          HReg        tLo = newVRegI(env);
   3702          HReg        tHi = newVRegI(env);
   3703          HReg        tmpHi;
   3704          HReg        tmpLo;
   3705          Bool        mode64 = env->mode64;
   3706 
   3707          argregs[0] = hregPPC_GPR3(mode64);
   3708          argregs[1] = hregPPC_GPR4(mode64);
   3709 
   3710          argiregs = 0;
   3711          argreg = 0;
   3712 
   3713          iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg, IEndianess);
   3714 
   3715          argiregs |= (1 << (argreg+3));
   3716          addInstr(env, mk_iMOVds_RR( argregs[argreg++], tmpHi ));
   3717 
   3718          argiregs |= (1 << (argreg+3));
   3719          addInstr(env, mk_iMOVds_RR( argregs[argreg], tmpLo));
   3720 
   3721          cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
   3722 
   3723          if (IEndianess == Iend_LE) {
   3724              addInstr(env, PPCInstr_Call( cc, (Addr)h_calc_DPBtoBCD,
   3725                                           argiregs,
   3726                                           mk_RetLoc_simple(RLPri_2Int) ) );
   3727          } else {
   3728              Addr64 target;
   3729              target = mode64 ? (Addr)h_calc_DPBtoBCD :
   3730                toUInt( (Addr)h_calc_DPBtoBCD );
   3731              addInstr(env, PPCInstr_Call( cc, target, argiregs,
   3732                                           mk_RetLoc_simple(RLPri_2Int) ) );
   3733          }
   3734 
   3735          addInstr(env, mk_iMOVds_RR(tHi, argregs[argreg-1]));
   3736          addInstr(env, mk_iMOVds_RR(tLo, argregs[argreg]));
   3737 
   3738          *rHi = tHi;
   3739          *rLo = tLo;
   3740          return;
   3741       }
   3742 
   3743       default:
   3744          break;
   3745       }
   3746    } /* if (e->tag == Iex_Unop) */
   3747 
   3748    vex_printf("iselInt64Expr(ppc): No such tag(%u)\n", e->tag);
   3749    ppIRExpr(e);
   3750    vpanic("iselInt64Expr(ppc)");
   3751 }
   3752 
   3753 
   3754 /*---------------------------------------------------------*/
   3755 /*--- ISEL: Floating point expressions (32 bit)         ---*/
   3756 /*---------------------------------------------------------*/
   3757 
   3758 /* Nothing interesting here; really just wrappers for
   3759    64-bit stuff. */
   3760 
   3761 static HReg iselFltExpr ( ISelEnv* env, IRExpr* e, IREndness IEndianess )
   3762 {
   3763   HReg r = iselFltExpr_wrk( env, e, IEndianess );
   3764 #  if 0
   3765    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
   3766 #  endif
   3767    vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
   3768    vassert(hregIsVirtual(r));
   3769    return r;
   3770 }
   3771 
   3772 /* DO NOT CALL THIS DIRECTLY */
   3773 static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e, IREndness IEndianess )
   3774 {
   3775    Bool        mode64 = env->mode64;
   3776 
   3777    IRType ty = typeOfIRExpr(env->type_env,e);
   3778    vassert(ty == Ity_F32);
   3779 
   3780    if (e->tag == Iex_RdTmp) {
   3781       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
   3782    }
   3783 
   3784    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
   3785       PPCAMode* am_addr;
   3786       HReg r_dst = newVRegF(env);
   3787       vassert(e->Iex.Load.ty == Ity_F32);
   3788       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F32/*xfer*/,
   3789                                    IEndianess);
   3790       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
   3791       return r_dst;
   3792    }
   3793 
   3794    if (e->tag == Iex_Get) {
   3795       HReg r_dst = newVRegF(env);
   3796       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
   3797                                        GuestStatePtr(env->mode64) );
   3798       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4, r_dst, am_addr ));
   3799       return r_dst;
   3800    }
   3801 
   3802    if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
   3803       /* This is quite subtle.  The only way to do the relevant
   3804          truncation is to do a single-precision store and then a
   3805          double precision load to get it back into a register.  The
   3806          problem is, if the data is then written to memory a second
   3807          time, as in
   3808 
   3809             STbe(...) = TruncF64asF32(...)
   3810 
   3811          then will the second truncation further alter the value?  The
   3812          answer is no: flds (as generated here) followed by fsts
   3813          (generated for the STbe) is the identity function on 32-bit
   3814          floats, so we are safe.
   3815 
   3816          Another upshot of this is that if iselStmt can see the
   3817          entirety of
   3818 
   3819             STbe(...) = TruncF64asF32(arg)
   3820 
   3821          then it can short circuit having to deal with TruncF64asF32
   3822          individually; instead just compute arg into a 64-bit FP
   3823          register and do 'fsts' (since that itself does the
   3824          truncation).
   3825 
   3826          We generate pretty poor code here (should be ok both for
   3827          32-bit and 64-bit mode); but it is expected that for the most
   3828          part the latter optimisation will apply and hence this code
   3829          will not often be used.
   3830       */
   3831       HReg      fsrc    = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
   3832       HReg      fdst    = newVRegF(env);
   3833       PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   3834 
   3835       sub_from_sp( env, 16 );
   3836       // store as F32, hence truncating
   3837       addInstr(env, PPCInstr_FpLdSt( False/*store*/, 4,
   3838                                      fsrc, zero_r1 ));
   3839       // and reload.  Good huh?! (sigh)
   3840       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 4,
   3841                                      fdst, zero_r1 ));
   3842       add_to_sp( env, 16 );
   3843       return fdst;
   3844    }
   3845 
   3846    if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64UtoF32) {
   3847       if (mode64) {
   3848          HReg fdst = newVRegF(env);
   3849          HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
   3850          HReg r1   = StackFramePtr(env->mode64);
   3851          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
   3852 
   3853          /* Set host rounding mode */
   3854          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   3855 
   3856          sub_from_sp( env, 16 );
   3857 
   3858          addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
   3859          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
   3860          addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
   3861                                        False, False,
   3862                                        fdst, fdst));
   3863 
   3864          add_to_sp( env, 16 );
   3865 
   3866          ///* Restore default FPU rounding. */
   3867          //set_FPU_rounding_default( env );
   3868          return fdst;
   3869       } else {
   3870          /* 32-bit mode */
   3871          HReg fdst = newVRegF(env);
   3872          HReg isrcHi, isrcLo;
   3873          HReg r1   = StackFramePtr(env->mode64);
   3874          PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
   3875          PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
   3876 
   3877          iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2, IEndianess);
   3878 
   3879          /* Set host rounding mode */
   3880          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   3881 
   3882          sub_from_sp( env, 16 );
   3883 
   3884          addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
   3885          addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
   3886          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
   3887          addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
   3888                                        False, False,
   3889                                        fdst, fdst));
   3890 
   3891          add_to_sp( env, 16 );
   3892 
   3893          ///* Restore default FPU rounding. */
   3894          //set_FPU_rounding_default( env );
   3895          return fdst;
   3896       }
   3897 
   3898    }
   3899 
   3900    vex_printf("iselFltExpr(ppc): No such tag(%u)\n", e->tag);
   3901    ppIRExpr(e);
   3902    vpanic("iselFltExpr_wrk(ppc)");
   3903 }
   3904 
   3905 
   3906 /*---------------------------------------------------------*/
   3907 /*--- ISEL: Floating point expressions (64 bit)         ---*/
   3908 /*---------------------------------------------------------*/
   3909 
   3910 /* Compute a 64-bit floating point value into a register, the identity
   3911    of which is returned.  As with iselIntExpr_R, the reg may be either
   3912    real or virtual; in any case it must not be changed by subsequent
   3913    code emitted by the caller.  */
   3914 
   3915 /* IEEE 754 formats.  From http://www.freesoft.org/CIE/RFC/1832/32.htm:
   3916 
   3917     Type                  S (1 bit)   E (11 bits)   F (52 bits)
   3918     ----                  ---------   -----------   -----------
   3919     signalling NaN        u           2047 (max)    .0uuuuu---u
   3920                                                     (with at least
   3921                                                      one 1 bit)
   3922     quiet NaN             u           2047 (max)    .1uuuuu---u
   3923 
   3924     negative infinity     1           2047 (max)    .000000---0
   3925 
   3926     positive infinity     0           2047 (max)    .000000---0
   3927 
   3928     negative zero         1           0             .000000---0
   3929 
   3930     positive zero         0           0             .000000---0
   3931 */
   3932 
   3933 static HReg iselDblExpr ( ISelEnv* env, IRExpr* e, IREndness IEndianess )
   3934 {
   3935    HReg r = iselDblExpr_wrk( env, e, IEndianess );
   3936 #  if 0
   3937    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
   3938 #  endif
   3939    vassert(hregClass(r) == HRcFlt64);
   3940    vassert(hregIsVirtual(r));
   3941    return r;
   3942 }
   3943 
   3944 /* DO NOT CALL THIS DIRECTLY */
   3945 static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e, IREndness IEndianess )
   3946 {
   3947    Bool mode64 = env->mode64;
   3948    IRType ty = typeOfIRExpr(env->type_env,e);
   3949    vassert(e);
   3950    vassert(ty == Ity_F64);
   3951 
   3952    if (e->tag == Iex_RdTmp) {
   3953       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
   3954    }
   3955 
   3956    /* --------- LITERAL --------- */
   3957    if (e->tag == Iex_Const) {
   3958       union { UInt u32x2[2]; ULong u64; Double f64; } u;
   3959       vassert(sizeof(u) == 8);
   3960       vassert(sizeof(u.u64) == 8);
   3961       vassert(sizeof(u.f64) == 8);
   3962       vassert(sizeof(u.u32x2) == 8);
   3963 
   3964       if (e->Iex.Const.con->tag == Ico_F64) {
   3965          u.f64 = e->Iex.Const.con->Ico.F64;
   3966       }
   3967       else if (e->Iex.Const.con->tag == Ico_F64i) {
   3968          u.u64 = e->Iex.Const.con->Ico.F64i;
   3969       }
   3970       else
   3971          vpanic("iselDblExpr(ppc): const");
   3972 
   3973       if (!mode64) {
   3974          HReg r_srcHi = newVRegI(env);
   3975          HReg r_srcLo = newVRegI(env);
   3976          addInstr(env, PPCInstr_LI(r_srcHi, u.u32x2[0], mode64));
   3977          addInstr(env, PPCInstr_LI(r_srcLo, u.u32x2[1], mode64));
   3978          return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
   3979       } else { // mode64
   3980          HReg r_src = newVRegI(env);
   3981          addInstr(env, PPCInstr_LI(r_src, u.u64, mode64));
   3982          return mk_LoadR64toFPR( env, r_src );         // 1*I64 -> F64
   3983       }
   3984    }
   3985 
   3986    /* --------- LOAD --------- */
   3987    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
   3988       HReg r_dst = newVRegF(env);
   3989       PPCAMode* am_addr;
   3990       vassert(e->Iex.Load.ty == Ity_F64);
   3991       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_F64/*xfer*/,
   3992                                    IEndianess);
   3993       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
   3994       return r_dst;
   3995    }
   3996 
   3997    /* --------- GET --------- */
   3998    if (e->tag == Iex_Get) {
   3999       HReg r_dst = newVRegF(env);
   4000       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
   4001                                        GuestStatePtr(mode64) );
   4002       addInstr(env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ));
   4003       return r_dst;
   4004    }
   4005 
   4006    /* --------- OPS --------- */
   4007    if (e->tag == Iex_Qop) {
   4008       PPCFpOp fpop = Pfp_INVALID;
   4009       switch (e->Iex.Qop.details->op) {
   4010          case Iop_MAddF64:    fpop = Pfp_MADDD; break;
   4011          case Iop_MAddF64r32: fpop = Pfp_MADDS; break;
   4012          case Iop_MSubF64:    fpop = Pfp_MSUBD; break;
   4013          case Iop_MSubF64r32: fpop = Pfp_MSUBS; break;
   4014          default: break;
   4015       }
   4016       if (fpop != Pfp_INVALID) {
   4017          HReg r_dst  = newVRegF(env);
   4018          HReg r_srcML  = iselDblExpr(env, e->Iex.Qop.details->arg2,
   4019                                      IEndianess);
   4020          HReg r_srcMR  = iselDblExpr(env, e->Iex.Qop.details->arg3,
   4021                                      IEndianess);
   4022          HReg r_srcAcc = iselDblExpr(env, e->Iex.Qop.details->arg4,
   4023                                      IEndianess);
   4024          set_FPU_rounding_mode( env, e->Iex.Qop.details->arg1, IEndianess );
   4025          addInstr(env, PPCInstr_FpMulAcc(fpop, r_dst,
   4026                                                r_srcML, r_srcMR, r_srcAcc));
   4027          return r_dst;
   4028       }
   4029    }
   4030 
   4031    if (e->tag == Iex_Triop) {
   4032       IRTriop *triop = e->Iex.Triop.details;
   4033       PPCFpOp fpop = Pfp_INVALID;
   4034       switch (triop->op) {
   4035          case Iop_AddF64:    fpop = Pfp_ADDD; break;
   4036          case Iop_SubF64:    fpop = Pfp_SUBD; break;
   4037          case Iop_MulF64:    fpop = Pfp_MULD; break;
   4038          case Iop_DivF64:    fpop = Pfp_DIVD; break;
   4039          case Iop_AddF64r32: fpop = Pfp_ADDS; break;
   4040          case Iop_SubF64r32: fpop = Pfp_SUBS; break;
   4041          case Iop_MulF64r32: fpop = Pfp_MULS; break;
   4042          case Iop_DivF64r32: fpop = Pfp_DIVS; break;
   4043          default: break;
   4044       }
   4045       if (fpop != Pfp_INVALID) {
   4046          HReg r_dst  = newVRegF(env);
   4047          HReg r_srcL = iselDblExpr(env, triop->arg2, IEndianess);
   4048          HReg r_srcR = iselDblExpr(env, triop->arg3, IEndianess);
   4049          set_FPU_rounding_mode( env, triop->arg1, IEndianess );
   4050          addInstr(env, PPCInstr_FpBinary(fpop, r_dst, r_srcL, r_srcR));
   4051          return r_dst;
   4052       }
   4053    }
   4054 
   4055    if (e->tag == Iex_Binop) {
   4056       PPCFpOp fpop = Pfp_INVALID;
   4057       switch (e->Iex.Binop.op) {
   4058       case Iop_SqrtF64:   fpop = Pfp_SQRT;   break;
   4059       default: break;
   4060       }
   4061       if (fpop == Pfp_SQRT) {
   4062          HReg fr_dst = newVRegF(env);
   4063          HReg fr_src = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
   4064          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   4065          addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
   4066          return fr_dst;
   4067       }
   4068    }
   4069 
   4070    if (e->tag == Iex_Binop) {
   4071 
   4072       if (e->Iex.Binop.op == Iop_RoundF64toF32) {
   4073          HReg r_dst = newVRegF(env);
   4074          HReg r_src = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
   4075          set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   4076          addInstr(env, PPCInstr_FpRSP(r_dst, r_src));
   4077          //set_FPU_rounding_default( env );
   4078          return r_dst;
   4079       }
   4080 
   4081       if (e->Iex.Binop.op == Iop_I64StoF64 || e->Iex.Binop.op == Iop_I64UtoF64) {
   4082          if (mode64) {
   4083             HReg fdst = newVRegF(env);
   4084             HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
   4085             HReg r1   = StackFramePtr(env->mode64);
   4086             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
   4087 
   4088             /* Set host rounding mode */
   4089             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   4090 
   4091             sub_from_sp( env, 16 );
   4092 
   4093             addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
   4094             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
   4095             addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
   4096                                           e->Iex.Binop.op == Iop_I64StoF64,
   4097                                           True/*fdst is 64 bit*/,
   4098                                           fdst, fdst));
   4099 
   4100             add_to_sp( env, 16 );
   4101 
   4102             ///* Restore default FPU rounding. */
   4103             //set_FPU_rounding_default( env );
   4104             return fdst;
   4105          } else {
   4106             /* 32-bit mode */
   4107             HReg fdst = newVRegF(env);
   4108             HReg isrcHi, isrcLo;
   4109             HReg r1   = StackFramePtr(env->mode64);
   4110             PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
   4111             PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
   4112 
   4113             iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2,
   4114                           IEndianess);
   4115 
   4116             /* Set host rounding mode */
   4117             set_FPU_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   4118 
   4119             sub_from_sp( env, 16 );
   4120 
   4121             addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
   4122             addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
   4123             addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
   4124             addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
   4125                                           e->Iex.Binop.op == Iop_I64StoF64,
   4126                                           True/*fdst is 64 bit*/,
   4127                                           fdst, fdst));
   4128 
   4129             add_to_sp( env, 16 );
   4130 
   4131             ///* Restore default FPU rounding. */
   4132             //set_FPU_rounding_default( env );
   4133             return fdst;
   4134          }
   4135       }
   4136 
   4137    }
   4138 
   4139    if (e->tag == Iex_Unop) {
   4140       PPCFpOp fpop = Pfp_INVALID;
   4141       switch (e->Iex.Unop.op) {
   4142          case Iop_NegF64:     fpop = Pfp_NEG; break;
   4143          case Iop_AbsF64:     fpop = Pfp_ABS; break;
   4144          case Iop_RSqrtEst5GoodF64:      fpop = Pfp_RSQRTE; break;
   4145          case Iop_RoundF64toF64_NegINF:  fpop = Pfp_FRIM; break;
   4146          case Iop_RoundF64toF64_PosINF:  fpop = Pfp_FRIP; break;
   4147          case Iop_RoundF64toF64_NEAREST: fpop = Pfp_FRIN; break;
   4148          case Iop_RoundF64toF64_ZERO:    fpop = Pfp_FRIZ; break;
   4149          default: break;
   4150       }
   4151       if (fpop != Pfp_INVALID) {
   4152          HReg fr_dst = newVRegF(env);
   4153          HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg, IEndianess);
   4154          addInstr(env, PPCInstr_FpUnary(fpop, fr_dst, fr_src));
   4155          return fr_dst;
   4156       }
   4157    }
   4158 
   4159    if (e->tag == Iex_Unop) {
   4160       switch (e->Iex.Unop.op) {
   4161          case Iop_ReinterpI64asF64: {
   4162             /* Given an I64, produce an IEEE754 double with the same
   4163                bit pattern. */
   4164             if (!mode64) {
   4165                HReg r_srcHi, r_srcLo;
   4166                iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg,
   4167                                IEndianess);
   4168                return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
   4169             } else {
   4170                HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   4171                return mk_LoadR64toFPR( env, r_src );
   4172             }
   4173          }
   4174 
   4175          case Iop_F32toF64: {
   4176             if (e->Iex.Unop.arg->tag == Iex_Unop &&
   4177                      e->Iex.Unop.arg->Iex.Unop.op == Iop_ReinterpI32asF32 ) {
   4178                e = e->Iex.Unop.arg;
   4179 
   4180                HReg src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   4181                HReg fr_dst = newVRegF(env);
   4182                PPCAMode *am_addr;
   4183 
   4184                sub_from_sp( env, 16 );        // Move SP down 16 bytes
   4185                am_addr = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   4186 
   4187                // store src as Ity_I32's
   4188                addInstr(env, PPCInstr_Store( 4, am_addr, src, env->mode64 ));
   4189 
   4190                // load single precision float, but the end results loads into a
   4191                // 64-bit FP register -- i.e., F64.
   4192                addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, fr_dst, am_addr));
   4193 
   4194                add_to_sp( env, 16 );          // Reset SP
   4195                return fr_dst;
   4196             }
   4197 
   4198 
   4199             /* this is a no-op */
   4200             HReg res = iselFltExpr(env, e->Iex.Unop.arg, IEndianess);
   4201             return res;
   4202          }
   4203          default:
   4204             break;
   4205       }
   4206    }
   4207 
   4208    /* --------- MULTIPLEX --------- */
   4209    if (e->tag == Iex_ITE) { // VFD
   4210       if (ty == Ity_F64
   4211           && typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) {
   4212          HReg fr1    = iselDblExpr(env, e->Iex.ITE.iftrue, IEndianess);
   4213          HReg fr0    = iselDblExpr(env, e->Iex.ITE.iffalse, IEndianess);
   4214          HReg fr_dst = newVRegF(env);
   4215          addInstr(env, PPCInstr_FpUnary( Pfp_MOV, fr_dst, fr0 ));
   4216          PPCCondCode cc = iselCondCode(env, e->Iex.ITE.cond, IEndianess);
   4217          addInstr(env, PPCInstr_FpCMov( cc, fr_dst, fr1 ));
   4218          return fr_dst;
   4219       }
   4220    }
   4221 
   4222    vex_printf("iselDblExpr(ppc): No such tag(%u)\n", e->tag);
   4223    ppIRExpr(e);
   4224    vpanic("iselDblExpr_wrk(ppc)");
   4225 }
   4226 
   4227 static HReg iselDfp32Expr(ISelEnv* env, IRExpr* e, IREndness IEndianess)
   4228 {
   4229    HReg r = iselDfp32Expr_wrk( env, e, IEndianess );
   4230    vassert(hregClass(r) == HRcFlt64);
   4231    vassert( hregIsVirtual(r) );
   4232    return r;
   4233 }
   4234 
   4235 /* DO NOT CALL THIS DIRECTLY */
   4236 static HReg iselDfp32Expr_wrk(ISelEnv* env, IRExpr* e, IREndness IEndianess)
   4237 {
   4238    Bool mode64 = env->mode64;
   4239    IRType ty = typeOfIRExpr( env->type_env, e );
   4240 
   4241    vassert( e );
   4242    vassert( ty == Ity_D32 );
   4243 
   4244    /* --------- GET --------- */
   4245    if (e->tag == Iex_Get) {
   4246       HReg r_dst = newVRegF( env );
   4247       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
   4248                                        GuestStatePtr(mode64) );
   4249       addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
   4250       return r_dst;
   4251    }
   4252 
   4253    /* --------- LOAD --------- */
   4254    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
   4255       PPCAMode* am_addr;
   4256       HReg r_dst = newVRegF(env);
   4257       vassert(e->Iex.Load.ty == Ity_D32);
   4258       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D32/*xfer*/,
   4259                                    IEndianess);
   4260       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
   4261       return r_dst;
   4262    }
   4263 
   4264    /* --------- OPS --------- */
   4265    if (e->tag == Iex_Binop) {
   4266       if (e->Iex.Binop.op == Iop_D64toD32) {
   4267          HReg fr_dst = newVRegF(env);
   4268          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
   4269          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   4270          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DRSP, fr_dst, fr_src));
   4271          return fr_dst;
   4272       }
   4273    }
   4274 
   4275    ppIRExpr( e );
   4276    vpanic( "iselDfp32Expr_wrk(ppc)" );
   4277 }
   4278 
   4279 static HReg iselDfp64Expr(ISelEnv* env, IRExpr* e, IREndness IEndianess)
   4280 {
   4281    HReg r = iselDfp64Expr_wrk( env, e, IEndianess );
   4282    vassert(hregClass(r) == HRcFlt64);
   4283    vassert( hregIsVirtual(r) );
   4284    return r;
   4285 }
   4286 
   4287 /* DO NOT CALL THIS DIRECTLY */
   4288 static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e, IREndness IEndianess)
   4289 {
   4290    Bool mode64 = env->mode64;
   4291    IRType ty = typeOfIRExpr( env->type_env, e );
   4292    HReg r_dstHi, r_dstLo;
   4293 
   4294    vassert( e );
   4295    vassert( ty == Ity_D64 );
   4296 
   4297    if (e->tag == Iex_RdTmp) {
   4298       return lookupIRTemp( env, e->Iex.RdTmp.tmp );
   4299    }
   4300 
   4301    /* --------- GET --------- */
   4302    if (e->tag == Iex_Get) {
   4303       HReg r_dst = newVRegF( env );
   4304       PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
   4305                                        GuestStatePtr(mode64) );
   4306       addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
   4307       return r_dst;
   4308    }
   4309 
   4310    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
   4311       PPCAMode* am_addr;
   4312       HReg r_dst = newVRegF(env);
   4313       vassert(e->Iex.Load.ty == Ity_D64);
   4314       am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D64/*xfer*/,
   4315                                    IEndianess);
   4316       addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
   4317       return r_dst;
   4318    }
   4319 
   4320    /* --------- OPS --------- */
   4321    if (e->tag == Iex_Qop) {
   4322       HReg r_dst = newVRegF( env );
   4323       return r_dst;
   4324    }
   4325 
   4326    if (e->tag == Iex_Unop) {
   4327       HReg fr_dst = newVRegF(env);
   4328       switch (e->Iex.Unop.op) {
   4329       case Iop_ReinterpI64asD64: {
   4330          /* Given an I64, produce an IEEE754 DFP with the same
   4331                bit pattern. */
   4332          if (!mode64) {
   4333             HReg r_srcHi, r_srcLo;
   4334             iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg,
   4335                            IEndianess);
   4336             return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
   4337          } else {
   4338             HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   4339             return mk_LoadR64toFPR( env, r_src );
   4340          }
   4341       }
   4342       case Iop_D32toD64: {
   4343          HReg fr_src = iselDfp32Expr(env, e->Iex.Unop.arg, IEndianess);
   4344          addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
   4345          return fr_dst;
   4346       }
   4347       case Iop_D128HItoD64:
   4348          iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg,
   4349                          IEndianess );
   4350          return r_dstHi;
   4351       case Iop_D128LOtoD64:
   4352          iselDfp128Expr( &r_dstHi, &r_dstLo, env, e->Iex.Unop.arg,
   4353                          IEndianess );
   4354          return r_dstLo;
   4355       case Iop_InsertExpD64: {
   4356          HReg fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1, IEndianess);
   4357          HReg fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2, IEndianess);
   4358 
   4359          addInstr(env, PPCInstr_Dfp64Binary(Pfp_DIEX, fr_dst, fr_srcL,
   4360 					    fr_srcR));
   4361          return fr_dst;
   4362        }
   4363       default:
   4364          vex_printf( "ERROR: iselDfp64Expr_wrk, UNKNOWN unop case %d\n",
   4365                      e->Iex.Unop.op );
   4366       }
   4367    }
   4368 
   4369    if (e->tag == Iex_Binop) {
   4370       PPCFpOp fpop = Pfp_INVALID;
   4371       HReg fr_dst = newVRegF(env);
   4372 
   4373       switch (e->Iex.Binop.op) {
   4374       case Iop_D128toD64:     fpop = Pfp_DRDPQ;  break;
   4375       case Iop_D64toD32:      fpop = Pfp_DRSP;   break;
   4376       case Iop_I64StoD64:     fpop = Pfp_DCFFIX; break;
   4377       case Iop_RoundD64toInt: fpop = Pfp_DRINTN; break;
   4378       default: break;
   4379       }
   4380       if (fpop == Pfp_DRDPQ) {
   4381          HReg r_srcHi = newVRegF(env);
   4382          HReg r_srcLo = newVRegF(env);
   4383 
   4384          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   4385          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
   4386                         IEndianess);
   4387          addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
   4388          return fr_dst;
   4389 
   4390       } else if (fpop == Pfp_DRINTN) {
   4391          HReg fr_src = newVRegF(env);
   4392          PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
   4393 
   4394          /* NOTE, this IOP takes a DFP value and rounds to the
   4395           * neares floating point integer value, i.e. fractional part
   4396           * is zero.  The result is a decimal floating point number.
   4397           * the INT in the name is a bit misleading.
   4398           */
   4399          fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
   4400          addInstr(env, PPCInstr_DfpRound(fr_dst, fr_src, r_rmc));
   4401          return fr_dst;
   4402 
   4403       } else if (fpop == Pfp_DRSP) {
   4404          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
   4405          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   4406          addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
   4407          return fr_dst;
   4408 
   4409       } else if (fpop == Pfp_DCFFIX) {
   4410          HReg fr_src = newVRegF(env);
   4411          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   4412 
   4413          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   4414          sub_from_sp( env, 16 );
   4415 
   4416          // put the I64 value into a floating point register
   4417          if (mode64) {
   4418            HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
   4419 
   4420            addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
   4421          } else {
   4422             HReg tmpHi, tmpLo;
   4423             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
   4424 
   4425             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Binop.arg2,
   4426                           IEndianess);
   4427             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
   4428             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
   4429          }
   4430 
   4431          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8,  fr_src, zero_r1));
   4432          addInstr(env, PPCInstr_Dfp64Unary(fpop, fr_dst, fr_src));
   4433          add_to_sp( env, 16 );
   4434          return fr_dst;
   4435       }
   4436 
   4437       switch (e->Iex.Binop.op) {
   4438       /* shift instructions D64, I32 -> D64 */
   4439       case Iop_ShlD64: fpop = Pfp_DSCLI; break;
   4440       case Iop_ShrD64: fpop = Pfp_DSCRI; break;
   4441       default: break;
   4442       }
   4443       if (fpop != Pfp_INVALID) {
   4444          HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg1, IEndianess);
   4445          PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
   4446 
   4447          /* shift value must be an immediate value */
   4448          vassert(shift->tag == Pri_Imm);
   4449 
   4450          addInstr(env, PPCInstr_DfpShift(fpop, fr_dst, fr_src, shift));
   4451          return fr_dst;
   4452       }
   4453 
   4454       switch (e->Iex.Binop.op) {
   4455       case Iop_InsertExpD64:
   4456          fpop = Pfp_DIEX;
   4457          break;
   4458       default: 	break;
   4459       }
   4460       if (fpop != Pfp_INVALID) {
   4461          HReg fr_srcL = newVRegF(env);
   4462          HReg fr_srcR = iselDfp64Expr(env, e->Iex.Binop.arg2, IEndianess);
   4463          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   4464          sub_from_sp( env, 16 );
   4465 
   4466          if (env->mode64) {
   4467             // put the I64 value into a floating point reg
   4468             HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   4469 
   4470             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
   4471          } else {
   4472             // put the I64 register pair into a floating point reg
   4473             HReg tmpHi;
   4474             HReg tmpLo;
   4475             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
   4476 
   4477             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Binop.arg1,
   4478                           IEndianess);
   4479             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*!mode64*/));
   4480             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*!mode64*/));
   4481          }
   4482          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_srcL, zero_r1));
   4483          addInstr(env, PPCInstr_Dfp64Binary(fpop, fr_dst, fr_srcL,
   4484                                             fr_srcR));
   4485          add_to_sp( env, 16 );
   4486          return fr_dst;
   4487       }
   4488    }
   4489 
   4490    if (e->tag == Iex_Triop) {
   4491       IRTriop *triop = e->Iex.Triop.details;
   4492       PPCFpOp fpop = Pfp_INVALID;
   4493 
   4494       switch (triop->op) {
   4495       case Iop_AddD64:
   4496          fpop = Pfp_DFPADD;
   4497          break;
   4498       case Iop_SubD64:
   4499          fpop = Pfp_DFPSUB;
   4500          break;
   4501       case Iop_MulD64:
   4502          fpop = Pfp_DFPMUL;
   4503          break;
   4504       case Iop_DivD64:
   4505          fpop = Pfp_DFPDIV;
   4506          break;
   4507       default:
   4508          break;
   4509       }
   4510       if (fpop != Pfp_INVALID) {
   4511          HReg r_dst = newVRegF( env );
   4512          HReg r_srcL = iselDfp64Expr( env, triop->arg2, IEndianess );
   4513          HReg r_srcR = iselDfp64Expr( env, triop->arg3, IEndianess );
   4514 
   4515          set_FPU_DFP_rounding_mode( env, triop->arg1, IEndianess );
   4516          addInstr( env, PPCInstr_Dfp64Binary( fpop, r_dst, r_srcL, r_srcR ) );
   4517          return r_dst;
   4518       }
   4519 
   4520       switch (triop->op) {
   4521       case Iop_QuantizeD64:          fpop = Pfp_DQUA;  break;
   4522       case Iop_SignificanceRoundD64: fpop = Pfp_RRDTR; break;
   4523       default: break;
   4524       }
   4525       if (fpop == Pfp_DQUA) {
   4526          HReg r_dst = newVRegF(env);
   4527          HReg r_srcL = iselDfp64Expr(env, triop->arg2, IEndianess);
   4528          HReg r_srcR = iselDfp64Expr(env, triop->arg3, IEndianess);
   4529          PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1, IEndianess);
   4530          addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR,
   4531                                             rmc));
   4532          return r_dst;
   4533 
   4534       } else if (fpop == Pfp_RRDTR) {
   4535          HReg r_dst = newVRegF(env);
   4536          HReg r_srcL = newVRegF(env);
   4537          HReg r_srcR = iselDfp64Expr(env, triop->arg3, IEndianess);
   4538          PPCRI* rmc  = iselWordExpr_RI(env, triop->arg1, IEndianess);
   4539          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   4540          HReg i8_val = iselWordExpr_R(env, triop->arg2, IEndianess);
   4541 
   4542          /* Move I8 to float register to issue instruction */
   4543          sub_from_sp( env, 16 );
   4544          if (mode64)
   4545             addInstr(env, PPCInstr_Store(8, zero_r1, i8_val, True/*mode64*/));
   4546          else
   4547             addInstr(env, PPCInstr_Store(4, zero_r1, i8_val, False/*mode32*/));
   4548 
   4549          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_srcL, zero_r1));
   4550          add_to_sp( env, 16 );
   4551 
   4552          // will set TE and RMC when issuing instruction
   4553          addInstr(env, PPCInstr_DfpQuantize(fpop, r_dst, r_srcL, r_srcR, rmc));
   4554          return r_dst;
   4555       }
   4556    }
   4557 
   4558    ppIRExpr( e );
   4559    vpanic( "iselDfp64Expr_wrk(ppc)" );
   4560 }
   4561 
   4562 static void iselDfp128Expr(HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e,
   4563                            IREndness IEndianess)
   4564 {
   4565    iselDfp128Expr_wrk( rHi, rLo, env, e, IEndianess );
   4566    vassert( hregIsVirtual(*rHi) );
   4567    vassert( hregIsVirtual(*rLo) );
   4568 }
   4569 
   4570 /* DO NOT CALL THIS DIRECTLY */
   4571 static void iselDfp128Expr_wrk(HReg* rHi, HReg *rLo, ISelEnv* env, IRExpr* e,
   4572                                IREndness IEndianess)
   4573 {
   4574    vassert( e );
   4575    vassert( typeOfIRExpr(env->type_env,e) == Ity_D128 );
   4576 
   4577    /* read 128-bit IRTemp */
   4578    if (e->tag == Iex_RdTmp) {
   4579       lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp );
   4580       return;
   4581    }
   4582 
   4583    if (e->tag == Iex_Unop) {
   4584       HReg r_dstHi = newVRegF(env);
   4585       HReg r_dstLo = newVRegF(env);
   4586 
   4587       if (e->Iex.Unop.op == Iop_I64StoD128) {
   4588          HReg fr_src = newVRegF(env);
   4589          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   4590 
   4591          // put the I64 value into a floating point reg
   4592          if (env->mode64) {
   4593             HReg tmp   = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   4594             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
   4595          } else {
   4596             HReg tmpHi, tmpLo;
   4597             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
   4598 
   4599             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg,
   4600                           IEndianess);
   4601             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
   4602             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
   4603          }
   4604 
   4605          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fr_src, zero_r1));
   4606          addInstr(env, PPCInstr_DfpI64StoD128(Pfp_DCFFIXQ, r_dstHi, r_dstLo,
   4607                                               fr_src));
   4608       }
   4609 
   4610       if (e->Iex.Unop.op == Iop_D64toD128) {
   4611          HReg r_src = iselDfp64Expr(env, e->Iex.Unop.arg, IEndianess);
   4612 
   4613          /* Source is 64bit, result is 128 bit.  High 64bit source arg,
   4614           * is ignored by the instruction.  Set high arg to r_src just
   4615           * to meet the vassert tests.
   4616           */
   4617          addInstr(env, PPCInstr_Dfp128Unary(Pfp_DCTQPQ, r_dstHi, r_dstLo,
   4618                                             r_src, r_src));
   4619       }
   4620       *rHi = r_dstHi;
   4621       *rLo = r_dstLo;
   4622       return;
   4623    }
   4624 
   4625    /* --------- OPS --------- */
   4626    if (e->tag == Iex_Binop) {
   4627       HReg r_srcHi;
   4628       HReg r_srcLo;
   4629 
   4630       switch (e->Iex.Binop.op) {
   4631       case Iop_D64HLtoD128:
   4632          r_srcHi = iselDfp64Expr( env, e->Iex.Binop.arg1, IEndianess );
   4633          r_srcLo = iselDfp64Expr( env, e->Iex.Binop.arg2, IEndianess );
   4634          *rHi = r_srcHi;
   4635          *rLo = r_srcLo;
   4636          return;
   4637          break;
   4638       case Iop_D128toD64: {
   4639          PPCFpOp fpop = Pfp_DRDPQ;
   4640          HReg fr_dst  = newVRegF(env);
   4641 
   4642          set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1, IEndianess );
   4643          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
   4644                         IEndianess);
   4645          addInstr(env, PPCInstr_DfpD128toD64(fpop, fr_dst, r_srcHi, r_srcLo));
   4646 
   4647          /* Need to meet the interface spec but the result is
   4648           * just 64-bits so send the result back in both halfs.
   4649           */
   4650          *rHi = fr_dst;
   4651          *rLo = fr_dst;
   4652          return;
   4653       }
   4654       case Iop_ShlD128:
   4655       case Iop_ShrD128: {
   4656          HReg fr_dst_hi = newVRegF(env);
   4657          HReg fr_dst_lo = newVRegF(env);
   4658          PPCRI* shift = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
   4659          PPCFpOp fpop = Pfp_DSCLIQ;  /* fix later if necessary */
   4660 
   4661          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg1,
   4662                         IEndianess);
   4663 
   4664          if (e->Iex.Binop.op == Iop_ShrD128)
   4665             fpop = Pfp_DSCRIQ;
   4666 
   4667          addInstr(env, PPCInstr_DfpShift128(fpop, fr_dst_hi, fr_dst_lo,
   4668                                             r_srcHi, r_srcLo, shift));
   4669 
   4670          *rHi = fr_dst_hi;
   4671          *rLo = fr_dst_lo;
   4672          return;
   4673       }
   4674       case Iop_RoundD128toInt: {
   4675          HReg r_dstHi = newVRegF(env);
   4676          HReg r_dstLo = newVRegF(env);
   4677          PPCRI* r_rmc = iselWordExpr_RI(env, e->Iex.Binop.arg1, IEndianess);
   4678 
   4679          // will set R and RMC when issuing instruction
   4680          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
   4681                         IEndianess);
   4682 
   4683          addInstr(env, PPCInstr_DfpRound128(r_dstHi, r_dstLo,
   4684                                             r_srcHi, r_srcLo, r_rmc));
   4685          *rHi = r_dstHi;
   4686          *rLo = r_dstLo;
   4687          return;
   4688       }
   4689       case Iop_InsertExpD128: {
   4690          HReg r_dstHi = newVRegF(env);
   4691          HReg r_dstLo = newVRegF(env);
   4692          HReg r_srcL  = newVRegF(env);
   4693          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   4694          r_srcHi = newVRegF(env);
   4695          r_srcLo = newVRegF(env);
   4696 
   4697          iselDfp128Expr(&r_srcHi, &r_srcLo, env, e->Iex.Binop.arg2,
   4698                         IEndianess);
   4699 
   4700          /* Move I64 to float register to issue instruction */
   4701          if (env->mode64) {
   4702             HReg tmp = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   4703             addInstr(env, PPCInstr_Store(8, zero_r1, tmp, True/*mode64*/));
   4704          } else {
   4705             HReg tmpHi, tmpLo;
   4706             PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
   4707 
   4708             iselInt64Expr(&tmpHi, &tmpLo, env, e->Iex.Unop.arg,
   4709                           IEndianess);
   4710             addInstr(env, PPCInstr_Store(4, zero_r1, tmpHi, False/*mode32*/));
   4711             addInstr(env, PPCInstr_Store(4, four_r1, tmpLo, False/*mode32*/));
   4712          }
   4713 
   4714          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_srcL, zero_r1));
   4715          addInstr(env, PPCInstr_InsertExpD128(Pfp_DIEXQ,
   4716                                               r_dstHi, r_dstLo,
   4717                                               r_srcL, r_srcHi, r_srcLo));
   4718          *rHi = r_dstHi;
   4719          *rLo = r_dstLo;
   4720          return;
   4721       }
   4722       default:
   4723          vex_printf( "ERROR: iselDfp128Expr_wrk, UNKNOWN binop case %d\n",
   4724                      e->Iex.Binop.op );
   4725          break;
   4726       }
   4727    }
   4728 
   4729    if (e->tag == Iex_Triop) {
   4730       IRTriop *triop = e->Iex.Triop.details;
   4731       PPCFpOp fpop = Pfp_INVALID;
   4732       HReg r_dstHi = newVRegF(env);
   4733       HReg r_dstLo = newVRegF(env);
   4734 
   4735       switch (triop->op) {
   4736       case Iop_AddD128:
   4737          fpop = Pfp_DFPADDQ;
   4738          break;
   4739       case Iop_SubD128:
   4740          fpop = Pfp_DFPSUBQ;
   4741          break;
   4742       case Iop_MulD128:
   4743          fpop = Pfp_DFPMULQ;
   4744          break;
   4745       case Iop_DivD128:
   4746          fpop = Pfp_DFPDIVQ;
   4747          break;
   4748       default:
   4749          break;
   4750       }
   4751 
   4752       if (fpop != Pfp_INVALID) {
   4753          HReg r_srcRHi = newVRegV( env );
   4754          HReg r_srcRLo = newVRegV( env );
   4755 
   4756          /* dst will be used to pass in the left operand and get the result. */
   4757          iselDfp128Expr( &r_dstHi, &r_dstLo, env, triop->arg2, IEndianess );
   4758          iselDfp128Expr( &r_srcRHi, &r_srcRLo, env, triop->arg3, IEndianess );
   4759          set_FPU_DFP_rounding_mode( env, triop->arg1, IEndianess );
   4760          addInstr( env,
   4761                    PPCInstr_Dfp128Binary( fpop, r_dstHi, r_dstLo,
   4762                                           r_srcRHi, r_srcRLo ) );
   4763          *rHi = r_dstHi;
   4764          *rLo = r_dstLo;
   4765          return;
   4766       }
   4767       switch (triop->op) {
   4768       case Iop_QuantizeD128:          fpop = Pfp_DQUAQ;  break;
   4769       case Iop_SignificanceRoundD128: fpop = Pfp_DRRNDQ; break;
   4770       default: break;
   4771       }
   4772       if (fpop == Pfp_DQUAQ) {
   4773          HReg r_srcHi = newVRegF(env);
   4774          HReg r_srcLo = newVRegF(env);
   4775          PPCRI* rmc = iselWordExpr_RI(env, triop->arg1, IEndianess);
   4776 
   4777          /* dst will be used to pass in the left operand and get the result */
   4778          iselDfp128Expr(&r_dstHi, &r_dstLo, env, triop->arg2, IEndianess);
   4779          iselDfp128Expr(&r_srcHi, &r_srcLo, env, triop->arg3, IEndianess);
   4780 
   4781          // will set RMC when issuing instruction
   4782          addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
   4783                                                r_srcHi, r_srcLo, rmc));
   4784         *rHi = r_dstHi;
   4785         *rLo = r_dstLo;
   4786          return;
   4787 
   4788       } else if (fpop == Pfp_DRRNDQ) {
   4789          HReg r_srcHi = newVRegF(env);
   4790          HReg r_srcLo = newVRegF(env);
   4791          PPCRI* rmc = iselWordExpr_RI(env, triop->arg1, IEndianess);
   4792          PPCAMode* zero_r1 = PPCAMode_IR( 0, StackFramePtr(env->mode64) );
   4793          PPCAMode* four_r1 = PPCAMode_IR( 4, StackFramePtr(env->mode64) );
   4794          HReg i8_val = iselWordExpr_R(env, triop->arg2, IEndianess);
   4795          HReg r_zero = newVRegI( env );
   4796 
   4797          iselDfp128Expr(&r_srcHi, &r_srcLo, env, triop->arg3, IEndianess);
   4798 
   4799          /* dst will be used to pass in the left operand and get the result */
   4800          /* Move I8 to float register to issue instruction.  Note, the
   4801           * instruction only looks at the bottom 6 bits so we really don't
   4802           * have to clear the upper bits since the iselWordExpr_R sets the
   4803           * bottom 8-bits.
   4804           */
   4805          sub_from_sp( env, 16 );
   4806 
   4807          if (env->mode64)
   4808             addInstr(env, PPCInstr_Store(4, four_r1, i8_val, True/*mode64*/));
   4809          else
   4810             addInstr(env, PPCInstr_Store(4, four_r1, i8_val, False/*mode32*/));
   4811 
   4812          /* Have to write to the upper bits to ensure they have been
   4813           * initialized. The instruction ignores all but the lower 6-bits.
   4814           */
   4815          addInstr( env, PPCInstr_LI( r_zero, 0, env->mode64 ) );
   4816          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dstHi, zero_r1));
   4817          addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dstLo, zero_r1));
   4818 
   4819          add_to_sp( env, 16 );
   4820 
   4821          // will set RMC when issuing instruction
   4822          addInstr(env, PPCInstr_DfpQuantize128(fpop, r_dstHi, r_dstLo,
   4823                                                r_srcHi, r_srcLo, rmc));
   4824          *rHi = r_dstHi;
   4825          *rLo = r_dstLo;
   4826          return;
   4827       }
   4828  }
   4829 
   4830    ppIRExpr( e );
   4831    vpanic( "iselDfp128Expr(ppc64)" );
   4832 }
   4833 
   4834 
   4835 /*---------------------------------------------------------*/
   4836 /*--- ISEL: SIMD (Vector) expressions, 128 bit.         ---*/
   4837 /*---------------------------------------------------------*/
   4838 
   4839 static HReg iselVecExpr ( ISelEnv* env, IRExpr* e, IREndness IEndianess )
   4840 {
   4841    HReg r = iselVecExpr_wrk( env, e, IEndianess );
   4842 #  if 0
   4843    vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
   4844 #  endif
   4845    vassert(hregClass(r) == HRcVec128);
   4846    vassert(hregIsVirtual(r));
   4847    return r;
   4848 }
   4849 
   4850 /* DO NOT CALL THIS DIRECTLY */
   4851 static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e, IREndness IEndianess )
   4852 {
   4853    Bool mode64 = env->mode64;
   4854    PPCAvOp op = Pav_INVALID;
   4855    PPCAvFpOp fpop = Pavfp_INVALID;
   4856    IRType  ty = typeOfIRExpr(env->type_env,e);
   4857    vassert(e);
   4858    vassert(ty == Ity_V128);
   4859 
   4860    if (e->tag == Iex_RdTmp) {
   4861       return lookupIRTemp(env, e->Iex.RdTmp.tmp);
   4862    }
   4863 
   4864    if (e->tag == Iex_Get) {
   4865       /* Guest state vectors are 16byte aligned,
   4866          so don't need to worry here */
   4867       HReg dst = newVRegV(env);
   4868       addInstr(env,
   4869                PPCInstr_AvLdSt( True/*load*/, 16, dst,
   4870                                 PPCAMode_IR( e->Iex.Get.offset,
   4871                                              GuestStatePtr(mode64) )));
   4872       return dst;
   4873    }
   4874 
   4875    if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) {
   4876       /* Need to be able to do V128 unaligned loads. The BE unaligned load
   4877        * can be accomplised using the following code sequece from the ISA.
   4878        * It uses the lvx instruction that does two aligned loads and then
   4879        * permute the data to store the required data as if it had been an
   4880        * unaligned load.
   4881        *
   4882        *   lvx  Vhi,0,Rb        # load MSQ, using the unaligned address in Rb
   4883        *   lvsl Vp, 0,Rb        # Set permute control vector
   4884        *   addi Rb,Rb,15        # Address of LSQ
   4885        *   lvx  Vlo,0,Rb        # load LSQ
   4886        *   vperm Vt,Vhi,Vlo,Vp  # align the data as requested
   4887        */
   4888 
   4889       HReg Vhi   = newVRegV(env);
   4890       HReg Vlo   = newVRegV(env);
   4891       HReg Vp    = newVRegV(env);
   4892       HReg v_dst = newVRegV(env);
   4893       HReg rB;
   4894       HReg rB_plus_15 = newVRegI(env);
   4895 
   4896       vassert(e->Iex.Load.ty == Ity_V128);
   4897       rB = iselWordExpr_R( env, e->Iex.Load.addr, IEndianess );
   4898 
   4899       // lvx  Vhi, 0, Rb
   4900       addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, Vhi,
   4901                                      PPCAMode_IR(0, rB)) );
   4902 
   4903       if (IEndianess == Iend_LE)
   4904          // lvsr Vp, 0, Rb
   4905          addInstr(env, PPCInstr_AvSh( False/*right shift*/, Vp,
   4906                                       PPCAMode_IR(0, rB)) );
   4907       else
   4908          // lvsl Vp, 0, Rb
   4909          addInstr(env, PPCInstr_AvSh( True/*left shift*/, Vp,
   4910                                       PPCAMode_IR(0, rB)) );
   4911 
   4912       // addi Rb_plus_15, Rb, 15
   4913       addInstr(env, PPCInstr_Alu( Palu_ADD, rB_plus_15,
   4914                                   rB, PPCRH_Imm(True, toUShort(15))) );
   4915 
   4916       // lvx  Vlo, 0, Rb_plus_15
   4917       addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, Vlo,
   4918                                      PPCAMode_IR(0, rB_plus_15)) );
   4919 
   4920       if (IEndianess == Iend_LE)
   4921          // vperm Vt, Vhi, Vlo, Vp
   4922          addInstr(env, PPCInstr_AvPerm( v_dst, Vlo, Vhi, Vp ));
   4923       else
   4924          // vperm Vt, Vhi, Vlo, Vp
   4925          addInstr(env, PPCInstr_AvPerm( v_dst, Vhi, Vlo, Vp ));
   4926 
   4927       return v_dst;
   4928    }
   4929 
   4930    if (e->tag == Iex_Unop) {
   4931       switch (e->Iex.Unop.op) {
   4932 
   4933       case Iop_NotV128: {
   4934          HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
   4935          HReg dst = newVRegV(env);
   4936          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, arg));
   4937          return dst;
   4938       }
   4939 
   4940       case Iop_CmpNEZ8x16: {
   4941          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
   4942          HReg zero = newVRegV(env);
   4943          HReg dst  = newVRegV(env);
   4944          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
   4945          addInstr(env, PPCInstr_AvBin8x16(Pav_CMPEQU, dst, arg, zero));
   4946          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
   4947          return dst;
   4948       }
   4949 
   4950       case Iop_CmpNEZ16x8: {
   4951          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
   4952          HReg zero = newVRegV(env);
   4953          HReg dst  = newVRegV(env);
   4954          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
   4955          addInstr(env, PPCInstr_AvBin16x8(Pav_CMPEQU, dst, arg, zero));
   4956          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
   4957          return dst;
   4958       }
   4959 
   4960       case Iop_CmpNEZ32x4: {
   4961          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
   4962          HReg zero = newVRegV(env);
   4963          HReg dst  = newVRegV(env);
   4964          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
   4965          addInstr(env, PPCInstr_AvBin32x4(Pav_CMPEQU, dst, arg, zero));
   4966          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
   4967          return dst;
   4968       }
   4969 
   4970       case Iop_CmpNEZ64x2: {
   4971          HReg arg  = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
   4972          HReg zero = newVRegV(env);
   4973          HReg dst  = newVRegV(env);
   4974          addInstr(env, PPCInstr_AvBinary(Pav_XOR, zero, zero, zero));
   4975          addInstr(env, PPCInstr_AvBin64x2(Pav_CMPEQU, dst, arg, zero));
   4976          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
   4977          return dst;
   4978       }
   4979 
   4980       case Iop_RecipEst32Fx4: fpop = Pavfp_RCPF;    goto do_32Fx4_unary;
   4981       case Iop_RSqrtEst32Fx4: fpop = Pavfp_RSQRTF;  goto do_32Fx4_unary;
   4982       case Iop_I32UtoFx4:     fpop = Pavfp_CVTU2F;  goto do_32Fx4_unary;
   4983       case Iop_I32StoFx4:     fpop = Pavfp_CVTS2F;  goto do_32Fx4_unary;
   4984       case Iop_QFtoI32Ux4_RZ: fpop = Pavfp_QCVTF2U; goto do_32Fx4_unary;
   4985       case Iop_QFtoI32Sx4_RZ: fpop = Pavfp_QCVTF2S; goto do_32Fx4_unary;
   4986       case Iop_RoundF32x4_RM: fpop = Pavfp_ROUNDM;  goto do_32Fx4_unary;
   4987       case Iop_RoundF32x4_RP: fpop = Pavfp_ROUNDP;  goto do_32Fx4_unary;
   4988       case Iop_RoundF32x4_RN: fpop = Pavfp_ROUNDN;  goto do_32Fx4_unary;
   4989       case Iop_RoundF32x4_RZ: fpop = Pavfp_ROUNDZ;  goto do_32Fx4_unary;
   4990       do_32Fx4_unary:
   4991       {
   4992          HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
   4993          HReg dst = newVRegV(env);
   4994          addInstr(env, PPCInstr_AvUn32Fx4(fpop, dst, arg));
   4995          return dst;
   4996       }
   4997 
   4998       case Iop_32UtoV128: {
   4999          HReg r_aligned16, r_zeros;
   5000          HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg, IEndianess);
   5001          HReg   dst = newVRegV(env);
   5002          PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
   5003          sub_from_sp( env, 32 );     // Move SP down
   5004 
   5005          /* Get a quadword aligned address within our stack space */
   5006          r_aligned16 = get_sp_aligned16( env );
   5007          am_off0  = PPCAMode_IR( 0,  r_aligned16 );
   5008          am_off4  = PPCAMode_IR( 4,  r_aligned16 );
   5009          am_off8  = PPCAMode_IR( 8,  r_aligned16 );
   5010          am_off12 = PPCAMode_IR( 12, r_aligned16 );
   5011 
   5012          /* Store zeros */
   5013          r_zeros = newVRegI(env);
   5014          addInstr(env, PPCInstr_LI(r_zeros, 0x0, mode64));
   5015          if (IEndianess == Iend_LE)
   5016             addInstr(env, PPCInstr_Store( 4, am_off0, r_src, mode64 ));
   5017          else
   5018             addInstr(env, PPCInstr_Store( 4, am_off0, r_zeros, mode64 ));
   5019          addInstr(env, PPCInstr_Store( 4, am_off4, r_zeros, mode64 ));
   5020          addInstr(env, PPCInstr_Store( 4, am_off8, r_zeros, mode64 ));
   5021 
   5022          /* Store r_src in low word of quadword-aligned mem */
   5023          if (IEndianess == Iend_LE)
   5024             addInstr(env, PPCInstr_Store( 4, am_off12, r_zeros, mode64 ));
   5025          else
   5026             addInstr(env, PPCInstr_Store( 4, am_off12, r_src, mode64 ));
   5027 
   5028          /* Load word into low word of quadword vector reg */
   5029          if (IEndianess == Iend_LE)
   5030             addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off0 ));
   5031          else
   5032             addInstr(env, PPCInstr_AvLdSt( True/*ld*/, 4, dst, am_off12 ));
   5033 
   5034          add_to_sp( env, 32 );       // Reset SP
   5035          return dst;
   5036       }
   5037 
   5038       case Iop_Dup8x16:
   5039       case Iop_Dup16x8:
   5040       case Iop_Dup32x4:
   5041          return mk_AvDuplicateRI(env, e->Iex.Unop.arg, IEndianess);
   5042 
   5043       case Iop_CipherSV128: op = Pav_CIPHERSUBV128; goto do_AvCipherV128Un;
   5044       do_AvCipherV128Un: {
   5045          HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
   5046          HReg dst = newVRegV(env);
   5047          addInstr(env, PPCInstr_AvCipherV128Unary(op, dst, arg));
   5048          return dst;
   5049       }
   5050 
   5051       case Iop_Clz8x16: op = Pav_ZEROCNTBYTE;   goto do_zerocnt;
   5052       case Iop_Clz16x8: op = Pav_ZEROCNTHALF;   goto do_zerocnt;
   5053       case Iop_Clz32x4: op = Pav_ZEROCNTWORD;   goto do_zerocnt;
   5054       case Iop_Clz64x2: op = Pav_ZEROCNTDBL;    goto do_zerocnt;
   5055       case Iop_PwBitMtxXpose64x2: op = Pav_BITMTXXPOSE;  goto do_zerocnt;
   5056       do_zerocnt:
   5057       {
   5058         HReg arg = iselVecExpr(env, e->Iex.Unop.arg, IEndianess);
   5059         HReg dst = newVRegV(env);
   5060         addInstr(env, PPCInstr_AvUnary(op, dst, arg));
   5061         return dst;
   5062       }
   5063 
   5064       default:
   5065          break;
   5066       } /* switch (e->Iex.Unop.op) */
   5067    } /* if (e->tag == Iex_Unop) */
   5068 
   5069    if (e->tag == Iex_Binop) {
   5070       switch (e->Iex.Binop.op) {
   5071 
   5072       case Iop_64HLtoV128: {
   5073          if (!mode64) {
   5074             HReg     r3, r2, r1, r0, r_aligned16;
   5075             PPCAMode *am_off0, *am_off4, *am_off8, *am_off12;
   5076             HReg     dst = newVRegV(env);
   5077             /* do this via the stack (easy, convenient, etc) */
   5078             sub_from_sp( env, 32 );        // Move SP down
   5079 
   5080             // get a quadword aligned address within our stack space
   5081             r_aligned16 = get_sp_aligned16( env );
   5082             am_off0  = PPCAMode_IR( 0,  r_aligned16 );
   5083             am_off4  = PPCAMode_IR( 4,  r_aligned16 );
   5084             am_off8  = PPCAMode_IR( 8,  r_aligned16 );
   5085             am_off12 = PPCAMode_IR( 12, r_aligned16 );
   5086 
   5087             /* Do the less significant 64 bits */
   5088             iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2, IEndianess);
   5089             addInstr(env, PPCInstr_Store( 4, am_off12, r0, mode64 ));
   5090             addInstr(env, PPCInstr_Store( 4, am_off8,  r1, mode64 ));
   5091             /* Do the more significant 64 bits */
   5092             iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1, IEndianess);
   5093             addInstr(env, PPCInstr_Store( 4, am_off4, r2, mode64 ));
   5094             addInstr(env, PPCInstr_Store( 4, am_off0, r3, mode64 ));
   5095 
   5096             /* Fetch result back from stack. */
   5097             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
   5098 
   5099             add_to_sp( env, 32 );          // Reset SP
   5100             return dst;
   5101          } else {
   5102             HReg     rHi = iselWordExpr_R(env, e->Iex.Binop.arg1, IEndianess);
   5103             HReg     rLo = iselWordExpr_R(env, e->Iex.Binop.arg2, IEndianess);
   5104             HReg     dst = newVRegV(env);
   5105             HReg     r_aligned16;
   5106             PPCAMode *am_off0, *am_off8;
   5107             /* do this via the stack (easy, convenient, etc) */
   5108             sub_from_sp( env, 32 );        // Move SP down
   5109 
   5110             // get a quadword aligned address within our stack space
   5111             r_aligned16 = get_sp_aligned16( env );
   5112             am_off0  = PPCAMode_IR( 0,  r_aligned16 );
   5113             am_off8  = PPCAMode_IR( 8,  r_aligned16 );
   5114 
   5115             /* Store 2*I64 to stack */
   5116             if (IEndianess == Iend_LE) {
   5117                addInstr(env, PPCInstr_Store( 8, am_off0, rLo, mode64 ));
   5118                addInstr(env, PPCInstr_Store( 8, am_off8, rHi, mode64 ));
   5119             } else {
   5120                addInstr(env, PPCInstr_Store( 8, am_off0, rHi, mode64 ));
   5121                addInstr(env, PPCInstr_Store( 8, am_off8, rLo, mode64 ));
   5122             }
   5123             /* Fetch result back from stack. */
   5124             addInstr(env, PPCInstr_AvLdSt(True/*ld*/, 16, dst, am_off0));
   5125 
   5126             add_to_sp( env, 32 );          // Reset SP
   5127             return dst;
   5128          }
   5129       }
   5130 
   5131       case Iop_Max32Fx4:   fpop = Pavfp_MAXF;   goto do_32Fx4;
   5132       case Iop_Min32Fx4:   fpop = Pavfp_MINF;   goto do_32Fx4;
   5133       case Iop_CmpEQ32Fx4: fpop = Pavfp_CMPEQF; goto do_32Fx4;
   5134       case Iop_CmpGT32Fx4: fpop = Pavfp_CMPGTF; goto do_32Fx4;
   5135       case Iop_CmpGE32Fx4: fpop = Pavfp_CMPGEF; goto do_32Fx4;
   5136       do_32Fx4:
   5137       {
   5138          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5139          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
   5140          HReg dst = newVRegV(env);
   5141          addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
   5142          return dst;
   5143       }
   5144 
   5145       case Iop_CmpLE32Fx4: {
   5146          HReg argL = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5147          HReg argR = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
   5148          HReg dst = newVRegV(env);
   5149 
   5150          /* stay consistent with native ppc compares:
   5151             if a left/right lane holds a nan, return zeros for that lane
   5152             so: le == NOT(gt OR isNan)
   5153           */
   5154          HReg isNanLR = newVRegV(env);
   5155          HReg isNanL = isNan(env, argL, IEndianess);
   5156          HReg isNanR = isNan(env, argR, IEndianess);
   5157          addInstr(env, PPCInstr_AvBinary(Pav_OR, isNanLR,
   5158                                          isNanL, isNanR));
   5159 
   5160          addInstr(env, PPCInstr_AvBin32Fx4(Pavfp_CMPGTF, dst,
   5161                                            argL, argR));
   5162          addInstr(env, PPCInstr_AvBinary(Pav_OR, dst, dst, isNanLR));
   5163          addInstr(env, PPCInstr_AvUnary(Pav_NOT, dst, dst));
   5164          return dst;
   5165       }
   5166 
   5167       case Iop_AndV128:    op = Pav_AND;      goto do_AvBin;
   5168       case Iop_OrV128:     op = Pav_OR;       goto do_AvBin;
   5169       case Iop_XorV128:    op = Pav_XOR;      goto do_AvBin;
   5170       do_AvBin: {
   5171          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5172          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
   5173          HReg dst  = newVRegV(env);
   5174          addInstr(env, PPCInstr_AvBinary(op, dst, arg1, arg2));
   5175          return dst;
   5176       }
   5177 
   5178       case Iop_Shl8x16:    op = Pav_SHL;    goto do_AvBin8x16;
   5179       case Iop_Shr8x16:    op = Pav_SHR;    goto do_AvBin8x16;
   5180       case Iop_Sar8x16:    op = Pav_SAR;    goto do_AvBin8x16;
   5181       case Iop_Rol8x16:    op = Pav_ROTL;   goto do_AvBin8x16;
   5182       case Iop_InterleaveHI8x16: op = Pav_MRGHI;  goto do_AvBin8x16;
   5183       case Iop_InterleaveLO8x16: op = Pav_MRGLO;  goto do_AvBin8x16;
   5184       case Iop_Add8x16:    op = Pav_ADDU;   goto do_AvBin8x16;
   5185       case Iop_QAdd8Ux16:  op = Pav_QADDU;  goto do_AvBin8x16;
   5186       case Iop_QAdd8Sx16:  op = Pav_QADDS;  goto do_AvBin8x16;
   5187       case Iop_Sub8x16:    op = Pav_SUBU;   goto do_AvBin8x16;
   5188       case Iop_QSub8Ux16:  op = Pav_QSUBU;  goto do_AvBin8x16;
   5189       case Iop_QSub8Sx16:  op = Pav_QSUBS;  goto do_AvBin8x16;
   5190       case Iop_Avg8Ux16:   op = Pav_AVGU;   goto do_AvBin8x16;
   5191       case Iop_Avg8Sx16:   op = Pav_AVGS;   goto do_AvBin8x16;
   5192       case Iop_Max8Ux16:   op = Pav_MAXU;   goto do_AvBin8x16;
   5193       case Iop_Max8Sx16:   op = Pav_MAXS;   goto do_AvBin8x16;
   5194       case Iop_Min8Ux16:   op = Pav_MINU;   goto do_AvBin8x16;
   5195       case Iop_Min8Sx16:   op = Pav_MINS;   goto do_AvBin8x16;
   5196       case Iop_MullEven8Ux16: op = Pav_OMULU;  goto do_AvBin8x16;
   5197       case Iop_MullEven8Sx16: op = Pav_OMULS;  goto do_AvBin8x16;
   5198       case Iop_CmpEQ8x16:  op = Pav_CMPEQU; goto do_AvBin8x16;
   5199       case Iop_CmpGT8Ux16: op = Pav_CMPGTU; goto do_AvBin8x16;
   5200       case Iop_CmpGT8Sx16: op = Pav_CMPGTS; goto do_AvBin8x16;
   5201       case Iop_PolynomialMulAdd8x16: op = Pav_POLYMULADD; goto do_AvBin8x16;
   5202       do_AvBin8x16: {
   5203          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5204          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
   5205          HReg dst  = newVRegV(env);
   5206          addInstr(env, PPCInstr_AvBin8x16(op, dst, arg1, arg2));
   5207          return dst;
   5208       }
   5209 
   5210       case Iop_Shl16x8:    op = Pav_SHL;    goto do_AvBin16x8;
   5211       case Iop_Shr16x8:    op = Pav_SHR;    goto do_AvBin16x8;
   5212       case Iop_Sar16x8:    op = Pav_SAR;    goto do_AvBin16x8;
   5213       case Iop_Rol16x8:    op = Pav_ROTL;   goto do_AvBin16x8;
   5214       case Iop_NarrowBin16to8x16:    op = Pav_PACKUU;  goto do_AvBin16x8;
   5215       case Iop_QNarrowBin16Uto8Ux16: op = Pav_QPACKUU; goto do_AvBin16x8;
   5216       case Iop_QNarrowBin16Sto8Sx16: op = Pav_QPACKSS; goto do_AvBin16x8;
   5217       case Iop_InterleaveHI16x8:  op = Pav_MRGHI;  goto do_AvBin16x8;
   5218       case Iop_InterleaveLO16x8:  op = Pav_MRGLO;  goto do_AvBin16x8;
   5219       case Iop_Add16x8:    op = Pav_ADDU;   goto do_AvBin16x8;
   5220       case Iop_QAdd16Ux8:  op = Pav_QADDU;  goto do_AvBin16x8;
   5221       case Iop_QAdd16Sx8:  op = Pav_QADDS;  goto do_AvBin16x8;
   5222       case Iop_Sub16x8:    op = Pav_SUBU;   goto do_AvBin16x8;
   5223       case Iop_QSub16Ux8:  op = Pav_QSUBU;  goto do_AvBin16x8;
   5224       case Iop_QSub16Sx8:  op = Pav_QSUBS;  goto do_AvBin16x8;
   5225       case Iop_Avg16Ux8:   op = Pav_AVGU;   goto do_AvBin16x8;
   5226       case Iop_Avg16Sx8:   op = Pav_AVGS;   goto do_AvBin16x8;
   5227       case Iop_Max16Ux8:   op = Pav_MAXU;   goto do_AvBin16x8;
   5228       case Iop_Max16Sx8:   op = Pav_MAXS;   goto do_AvBin16x8;
   5229       case Iop_Min16Ux8:   op = Pav_MINU;   goto do_AvBin16x8;
   5230       case Iop_Min16Sx8:   op = Pav_MINS;   goto do_AvBin16x8;
   5231       case Iop_MullEven16Ux8: op = Pav_OMULU;  goto do_AvBin16x8;
   5232       case Iop_MullEven16Sx8: op = Pav_OMULS;  goto do_AvBin16x8;
   5233       case Iop_CmpEQ16x8:  op = Pav_CMPEQU; goto do_AvBin16x8;
   5234       case Iop_CmpGT16Ux8: op = Pav_CMPGTU; goto do_AvBin16x8;
   5235       case Iop_CmpGT16Sx8: op = Pav_CMPGTS; goto do_AvBin16x8;
   5236       case Iop_PolynomialMulAdd16x8: op = Pav_POLYMULADD; goto do_AvBin16x8;
   5237       do_AvBin16x8: {
   5238          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5239          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
   5240          HReg dst  = newVRegV(env);
   5241          addInstr(env, PPCInstr_AvBin16x8(op, dst, arg1, arg2));
   5242          return dst;
   5243       }
   5244 
   5245       case Iop_Shl32x4:    op = Pav_SHL;    goto do_AvBin32x4;
   5246       case Iop_Shr32x4:    op = Pav_SHR;    goto do_AvBin32x4;
   5247       case Iop_Sar32x4:    op = Pav_SAR;    goto do_AvBin32x4;
   5248       case Iop_Rol32x4:    op = Pav_ROTL;   goto do_AvBin32x4;
   5249       case Iop_NarrowBin32to16x8:    op = Pav_PACKUU;  goto do_AvBin32x4;
   5250       case Iop_QNarrowBin32Uto16Ux8: op = Pav_QPACKUU; goto do_AvBin32x4;
   5251       case Iop_QNarrowBin32Sto16Sx8: op = Pav_QPACKSS; goto do_AvBin32x4;
   5252       case Iop_InterleaveHI32x4:  op = Pav_MRGHI;  goto do_AvBin32x4;
   5253       case Iop_InterleaveLO32x4:  op = Pav_MRGLO;  goto do_AvBin32x4;
   5254       case Iop_Add32x4:    op = Pav_ADDU;   goto do_AvBin32x4;
   5255       case Iop_QAdd32Ux4:  op = Pav_QADDU;  goto do_AvBin32x4;
   5256       case Iop_QAdd32Sx4:  op = Pav_QADDS;  goto do_AvBin32x4;
   5257       case Iop_Sub32x4:    op = Pav_SUBU;   goto do_AvBin32x4;
   5258       case Iop_QSub32Ux4:  op = Pav_QSUBU;  goto do_AvBin32x4;
   5259       case Iop_QSub32Sx4:  op = Pav_QSUBS;  goto do_AvBin32x4;
   5260       case Iop_Avg32Ux4:   op = Pav_AVGU;   goto do_AvBin32x4;
   5261       case Iop_Avg32Sx4:   op = Pav_AVGS;   goto do_AvBin32x4;
   5262       case Iop_Max32Ux4:   op = Pav_MAXU;   goto do_AvBin32x4;
   5263       case Iop_Max32Sx4:   op = Pav_MAXS;   goto do_AvBin32x4;
   5264       case Iop_Min32Ux4:   op = Pav_MINU;   goto do_AvBin32x4;
   5265       case Iop_Min32Sx4:   op = Pav_MINS;   goto do_AvBin32x4;
   5266       case Iop_Mul32x4:    op = Pav_MULU;   goto do_AvBin32x4;
   5267       case Iop_MullEven32Ux4: op = Pav_OMULU;  goto do_AvBin32x4;
   5268       case Iop_MullEven32Sx4: op = Pav_OMULS;  goto do_AvBin32x4;
   5269       case Iop_CmpEQ32x4:  op = Pav_CMPEQU; goto do_AvBin32x4;
   5270       case Iop_CmpGT32Ux4: op = Pav_CMPGTU; goto do_AvBin32x4;
   5271       case Iop_CmpGT32Sx4: op = Pav_CMPGTS; goto do_AvBin32x4;
   5272       case Iop_CatOddLanes32x4:  op = Pav_CATODD;  goto do_AvBin32x4;
   5273       case Iop_CatEvenLanes32x4: op = Pav_CATEVEN; goto do_AvBin32x4;
   5274       case Iop_PolynomialMulAdd32x4: op = Pav_POLYMULADD; goto do_AvBin32x4;
   5275       do_AvBin32x4: {
   5276          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5277          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
   5278          HReg dst  = newVRegV(env);
   5279          addInstr(env, PPCInstr_AvBin32x4(op, dst, arg1, arg2));
   5280          return dst;
   5281       }
   5282 
   5283       case Iop_Shl64x2:    op = Pav_SHL;    goto do_AvBin64x2;
   5284       case Iop_Shr64x2:    op = Pav_SHR;    goto do_AvBin64x2;
   5285       case Iop_Sar64x2:    op = Pav_SAR;    goto do_AvBin64x2;
   5286       case Iop_Rol64x2:    op = Pav_ROTL;   goto do_AvBin64x2;
   5287       case Iop_NarrowBin64to32x4:    op = Pav_PACKUU;  goto do_AvBin64x2;
   5288       case Iop_QNarrowBin64Sto32Sx4: op = Pav_QPACKSS; goto do_AvBin64x2;
   5289       case Iop_QNarrowBin64Uto32Ux4: op = Pav_QPACKUU; goto do_AvBin64x2;
   5290       case Iop_InterleaveHI64x2:  op = Pav_MRGHI;  goto do_AvBin64x2;
   5291       case Iop_InterleaveLO64x2:  op = Pav_MRGLO;  goto do_AvBin64x2;
   5292       case Iop_Add64x2:    op = Pav_ADDU;   goto do_AvBin64x2;
   5293       case Iop_Sub64x2:    op = Pav_SUBU;   goto do_AvBin64x2;
   5294       case Iop_Max64Ux2:   op = Pav_MAXU;   goto do_AvBin64x2;
   5295       case Iop_Max64Sx2:   op = Pav_MAXS;   goto do_AvBin64x2;
   5296       case Iop_Min64Ux2:   op = Pav_MINU;   goto do_AvBin64x2;
   5297       case Iop_Min64Sx2:   op = Pav_MINS;   goto do_AvBin64x2;
   5298       case Iop_CmpEQ64x2:  op = Pav_CMPEQU; goto do_AvBin64x2;
   5299       case Iop_CmpGT64Ux2: op = Pav_CMPGTU; goto do_AvBin64x2;
   5300       case Iop_CmpGT64Sx2: op = Pav_CMPGTS; goto do_AvBin64x2;
   5301       case Iop_PolynomialMulAdd64x2: op = Pav_POLYMULADD; goto do_AvBin64x2;
   5302       do_AvBin64x2: {
   5303          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5304          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
   5305          HReg dst  = newVRegV(env);
   5306          addInstr(env, PPCInstr_AvBin64x2(op, dst, arg1, arg2));
   5307          return dst;
   5308       }
   5309 
   5310       case Iop_ShlN8x16: op = Pav_SHL; goto do_AvShift8x16;
   5311       case Iop_SarN8x16: op = Pav_SAR; goto do_AvShift8x16;
   5312       do_AvShift8x16: {
   5313          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5314          HReg dst    = newVRegV(env);
   5315          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
   5316          addInstr(env, PPCInstr_AvBin8x16(op, dst, r_src, v_shft));
   5317          return dst;
   5318       }
   5319 
   5320       case Iop_ShlN16x8: op = Pav_SHL; goto do_AvShift16x8;
   5321       case Iop_ShrN16x8: op = Pav_SHR; goto do_AvShift16x8;
   5322       case Iop_SarN16x8: op = Pav_SAR; goto do_AvShift16x8;
   5323       do_AvShift16x8: {
   5324          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5325          HReg dst    = newVRegV(env);
   5326          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
   5327          addInstr(env, PPCInstr_AvBin16x8(op, dst, r_src, v_shft));
   5328          return dst;
   5329       }
   5330 
   5331       case Iop_ShlN32x4: op = Pav_SHL; goto do_AvShift32x4;
   5332       case Iop_ShrN32x4: op = Pav_SHR; goto do_AvShift32x4;
   5333       case Iop_SarN32x4: op = Pav_SAR; goto do_AvShift32x4;
   5334       do_AvShift32x4: {
   5335          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5336          HReg dst    = newVRegV(env);
   5337          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
   5338          addInstr(env, PPCInstr_AvBin32x4(op, dst, r_src, v_shft));
   5339          return dst;
   5340       }
   5341 
   5342       case Iop_ShlN64x2: op = Pav_SHL; goto do_AvShift64x2;
   5343       case Iop_ShrN64x2: op = Pav_SHR; goto do_AvShift64x2;
   5344       case Iop_SarN64x2: op = Pav_SAR; goto do_AvShift64x2;
   5345       do_AvShift64x2: {
   5346          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5347          HReg dst    = newVRegV(env);
   5348          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
   5349          addInstr(env, PPCInstr_AvBin64x2(op, dst, r_src, v_shft));
   5350          return dst;
   5351       }
   5352 
   5353       case Iop_ShrV128: op = Pav_SHR; goto do_AvShiftV128;
   5354       case Iop_ShlV128: op = Pav_SHL; goto do_AvShiftV128;
   5355       do_AvShiftV128: {
   5356          HReg dst    = newVRegV(env);
   5357          HReg r_src  = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5358          HReg v_shft = mk_AvDuplicateRI(env, e->Iex.Binop.arg2, IEndianess);
   5359          /* Note: shift value gets masked by 127 */
   5360          addInstr(env, PPCInstr_AvBinary(op, dst, r_src, v_shft));
   5361          return dst;
   5362       }
   5363 
   5364       case Iop_Perm8x16: {
   5365          HReg dst   = newVRegV(env);
   5366          HReg v_src = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5367          HReg v_ctl = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
   5368          addInstr(env, PPCInstr_AvPerm(dst, v_src, v_src, v_ctl));
   5369          return dst;
   5370       }
   5371 
   5372       case Iop_CipherV128:  op = Pav_CIPHERV128;   goto do_AvCipherV128;
   5373       case Iop_CipherLV128: op = Pav_CIPHERLV128;  goto do_AvCipherV128;
   5374       case Iop_NCipherV128: op = Pav_NCIPHERV128;  goto do_AvCipherV128;
   5375       case Iop_NCipherLV128:op = Pav_NCIPHERLV128; goto do_AvCipherV128;
   5376       do_AvCipherV128: {
   5377          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5378          HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2, IEndianess);
   5379          HReg dst  = newVRegV(env);
   5380          addInstr(env, PPCInstr_AvCipherV128Binary(op, dst, arg1, arg2));
   5381          return dst;
   5382       }
   5383 
   5384       case Iop_SHA256:op = Pav_SHA256; goto do_AvHashV128;
   5385       case Iop_SHA512:op = Pav_SHA512; goto do_AvHashV128;
   5386       do_AvHashV128: {
   5387          HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1, IEndianess);
   5388          HReg dst  = newVRegV(env);
   5389          PPCRI* s_field = iselWordExpr_RI(env, e->Iex.Binop.arg2, IEndianess);
   5390          addInstr(env, PPCInstr_AvHashV128Binary(op, dst, arg1, s_field));
   5391          return dst;
   5392       }
   5393       default:
   5394          break;
   5395       } /* switch (e->Iex.Binop.op) */
   5396    } /* if (e->tag == Iex_Binop) */
   5397 
   5398    if (e->tag == Iex_Triop) {
   5399       IRTriop *triop = e->Iex.Triop.details;
   5400       switch (triop->op) {
   5401       case Iop_BCDAdd:op = Pav_BCDAdd; goto do_AvBCDV128;
   5402       case Iop_BCDSub:op = Pav_BCDSub; goto do_AvBCDV128;
   5403       do_AvBCDV128: {
   5404          HReg arg1 = iselVecExpr(env, triop->arg1, IEndianess);
   5405          HReg arg2 = iselVecExpr(env, triop->arg2, IEndianess);
   5406          HReg dst  = newVRegV(env);
   5407          PPCRI* ps = iselWordExpr_RI(env, triop->arg3, IEndianess);
   5408          addInstr(env, PPCInstr_AvBCDV128Trinary(op, dst, arg1, arg2, ps));
   5409          return dst;
   5410       }
   5411 
   5412       case Iop_Add32Fx4: fpop = Pavfp_ADDF; goto do_32Fx4_with_rm;
   5413       case Iop_Sub32Fx4: fpop = Pavfp_SUBF; goto do_32Fx4_with_rm;
   5414       case Iop_Mul32Fx4: fpop = Pavfp_MULF; goto do_32Fx4_with_rm;
   5415       do_32Fx4_with_rm:
   5416       {
   5417          HReg argL = iselVecExpr(env, triop->arg2, IEndianess);
   5418          HReg argR = iselVecExpr(env, triop->arg3, IEndianess);
   5419          HReg dst  = newVRegV(env);
   5420          /* FIXME: this is bogus, in the sense that Altivec ignores
   5421             FPSCR.RM, at least for some FP operations.  So setting the
   5422             RM is pointless.  This is only really correct in the case
   5423             where the RM is known, at JIT time, to be Irrm_NEAREST,
   5424             since -- at least for Altivec FP add/sub/mul -- the
   5425             emitted insn is hardwired to round to nearest. */
   5426          set_FPU_rounding_mode(env, triop->arg1, IEndianess);
   5427          addInstr(env, PPCInstr_AvBin32Fx4(fpop, dst, argL, argR));
   5428          return dst;
   5429       }
   5430 
   5431       default:
   5432          break;
   5433       } /* switch (e->Iex.Triop.op) */
   5434    } /* if (e->tag == Iex_Trinop) */
   5435 
   5436 
   5437    if (e->tag == Iex_Const ) {
   5438       vassert(e->Iex.Const.con->tag == Ico_V128);
   5439       if (e->Iex.Const.con->Ico.V128 == 0x0000) {
   5440          return generate_zeroes_V128(env);
   5441       }
   5442       else if (e->Iex.Const.con->Ico.V128 == 0xffff) {
   5443          return generate_ones_V128(env);
   5444       }
   5445    }
   5446 
   5447    vex_printf("iselVecExpr(ppc) (subarch = %s): can't reduce\n",
   5448               LibVEX_ppVexHwCaps(mode64 ? VexArchPPC64 : VexArchPPC32,
   5449                                  env->hwcaps));
   5450    ppIRExpr(e);
   5451    vpanic("iselVecExpr_wrk(ppc)");
   5452 }
   5453 
   5454 
   5455 /*---------------------------------------------------------*/
   5456 /*--- ISEL: Statements                                  ---*/
   5457 /*---------------------------------------------------------*/
   5458 
   5459 static void iselStmt ( ISelEnv* env, IRStmt* stmt, IREndness IEndianess )
   5460 {
   5461    Bool mode64 = env->mode64;
   5462    if (vex_traceflags & VEX_TRACE_VCODE) {
   5463       vex_printf("\n -- ");
   5464       ppIRStmt(stmt);
   5465       vex_printf("\n");
   5466    }
   5467 
   5468    switch (stmt->tag) {
   5469 
   5470    /* --------- STORE --------- */
   5471    case Ist_Store: {
   5472       IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
   5473       IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
   5474       IREndness end   = stmt->Ist.Store.end;
   5475 
   5476       if (end != IEndianess)
   5477          goto stmt_fail;
   5478       if (!mode64 && (tya != Ity_I32))
   5479          goto stmt_fail;
   5480       if (mode64 && (tya != Ity_I64))
   5481          goto stmt_fail;
   5482 
   5483       if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
   5484           (mode64 && (tyd == Ity_I64))) {
   5485          PPCAMode* am_addr
   5486             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
   5487                                  IEndianess);
   5488          HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data, IEndianess);
   5489          addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(tyd)),
   5490                                        am_addr, r_src, mode64 ));
   5491          return;
   5492       }
   5493       if (tyd == Ity_F64) {
   5494          PPCAMode* am_addr
   5495             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
   5496                                  IEndianess);
   5497          HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data, IEndianess);
   5498          addInstr(env,
   5499                   PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
   5500          return;
   5501       }
   5502       if (tyd == Ity_F32) {
   5503          PPCAMode* am_addr
   5504             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
   5505                                  IEndianess);
   5506          HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data, IEndianess);
   5507          addInstr(env,
   5508                   PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
   5509          return;
   5510       }
   5511       if (tyd == Ity_D64) {
   5512          PPCAMode* am_addr
   5513             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
   5514                                  IEndianess);
   5515          HReg fr_src = iselDfp64Expr(env, stmt->Ist.Store.data, IEndianess);
   5516          addInstr(env,
   5517                   PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
   5518          return;
   5519       }
   5520       if (tyd == Ity_D32) {
   5521          PPCAMode* am_addr
   5522             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
   5523                                  IEndianess);
   5524          HReg fr_src = iselDfp32Expr(env, stmt->Ist.Store.data, IEndianess);
   5525          addInstr(env,
   5526                   PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
   5527          return;
   5528       }
   5529       if (tyd == Ity_V128) {
   5530          PPCAMode* am_addr
   5531             = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/,
   5532                                  IEndianess);
   5533          HReg v_src = iselVecExpr(env, stmt->Ist.Store.data, IEndianess);
   5534          addInstr(env,
   5535                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
   5536          return;
   5537       }
   5538       if (tyd == Ity_I64 && !mode64) {
   5539          /* Just calculate the address in the register.  Life is too
   5540             short to arse around trying and possibly failing to adjust
   5541             the offset in a 'reg+offset' style amode. */
   5542          HReg rHi32, rLo32;
   5543          HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr, IEndianess);
   5544          iselInt64Expr( &rHi32, &rLo32, env, stmt->Ist.Store.data,
   5545                         IEndianess );
   5546          addInstr(env, PPCInstr_Store( 4/*byte-store*/,
   5547                                        PPCAMode_IR( 0, r_addr ),
   5548                                        rHi32,
   5549                                        False/*32-bit insn please*/) );
   5550          addInstr(env, PPCInstr_Store( 4/*byte-store*/,
   5551                                        PPCAMode_IR( 4, r_addr ),
   5552                                        rLo32,
   5553                                        False/*32-bit insn please*/) );
   5554          return;
   5555       }
   5556       break;
   5557    }
   5558 
   5559    /* --------- PUT --------- */
   5560    case Ist_Put: {
   5561       IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
   5562       if (ty == Ity_I8  || ty == Ity_I16 ||
   5563           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
   5564          HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data, IEndianess);
   5565          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
   5566                                           GuestStatePtr(mode64) );
   5567          addInstr(env, PPCInstr_Store( toUChar(sizeofIRType(ty)),
   5568                                        am_addr, r_src, mode64 ));
   5569          return;
   5570       }
   5571       if (!mode64 && ty == Ity_I64) {
   5572          HReg rHi, rLo;
   5573          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
   5574                                            GuestStatePtr(mode64) );
   5575          PPCAMode* am_addr4 = advance4(env, am_addr);
   5576          iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Put.data, IEndianess);
   5577          addInstr(env, PPCInstr_Store( 4, am_addr,  rHi, mode64 ));
   5578          addInstr(env, PPCInstr_Store( 4, am_addr4, rLo, mode64 ));
   5579          return;
   5580      }
   5581      if (ty == Ity_V128) {
   5582          /* Guest state vectors are 16byte aligned,
   5583             so don't need to worry here */
   5584          HReg v_src = iselVecExpr(env, stmt->Ist.Put.data, IEndianess);
   5585          PPCAMode* am_addr  = PPCAMode_IR( stmt->Ist.Put.offset,
   5586                                            GuestStatePtr(mode64) );
   5587          addInstr(env,
   5588                   PPCInstr_AvLdSt(False/*store*/, 16, v_src, am_addr));
   5589          return;
   5590       }
   5591       if (ty == Ity_F64) {
   5592          HReg fr_src = iselDblExpr(env, stmt->Ist.Put.data, IEndianess);
   5593          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
   5594                                           GuestStatePtr(mode64) );
   5595          addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8,
   5596                                         fr_src, am_addr ));
   5597          return;
   5598       }
   5599       if (ty == Ity_D32) {
   5600          /* The 32-bit value is stored in a 64-bit register */
   5601          HReg fr_src = iselDfp32Expr( env, stmt->Ist.Put.data, IEndianess );
   5602          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
   5603                                           GuestStatePtr(mode64) );
   5604          addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8,
   5605                                          fr_src, am_addr ) );
   5606          return;
   5607       }
   5608       if (ty == Ity_D64) {
   5609          HReg fr_src = iselDfp64Expr( env, stmt->Ist.Put.data, IEndianess );
   5610          PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
   5611                                           GuestStatePtr(mode64) );
   5612          addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8, fr_src, am_addr ) );
   5613          return;
   5614       }
   5615       break;
   5616    }
   5617 
   5618    /* --------- Indexed PUT --------- */
   5619    case Ist_PutI: {
   5620       IRPutI *puti = stmt->Ist.PutI.details;
   5621 
   5622       PPCAMode* dst_am
   5623          = genGuestArrayOffset(
   5624               env, puti->descr,
   5625               puti->ix, puti->bias,
   5626               IEndianess );
   5627       IRType ty = typeOfIRExpr(env->type_env, puti->data);
   5628       if (mode64 && ty == Ity_I64) {
   5629          HReg r_src = iselWordExpr_R(env, puti->data, IEndianess);
   5630          addInstr(env, PPCInstr_Store( toUChar(8),
   5631                                        dst_am, r_src, mode64 ));
   5632          return;
   5633       }
   5634       if ((!mode64) && ty == Ity_I32) {
   5635          HReg r_src = iselWordExpr_R(env, puti->data, IEndianess);
   5636          addInstr(env, PPCInstr_Store( toUChar(4),
   5637                                        dst_am, r_src, mode64 ));
   5638          return;
   5639       }
   5640       break;
   5641    }
   5642 
   5643    /* --------- TMP --------- */
   5644    case Ist_WrTmp: {
   5645       IRTemp tmp = stmt->Ist.WrTmp.tmp;
   5646       IRType ty = typeOfIRTemp(env->type_env, tmp);
   5647       if (ty == Ity_I8  || ty == Ity_I16 ||
   5648           ty == Ity_I32 || ((ty == Ity_I64) && mode64)) {
   5649          HReg r_dst = lookupIRTemp(env, tmp);
   5650          HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data, IEndianess);
   5651          addInstr(env, mk_iMOVds_RR( r_dst, r_src ));
   5652          return;
   5653       }
   5654       if (!mode64 && ty == Ity_I64) {
   5655          HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
   5656 
   5657          iselInt64Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data,
   5658                        IEndianess);
   5659          lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
   5660          addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
   5661          addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
   5662          return;
   5663       }
   5664       if (mode64 && ty == Ity_I128) {
   5665          HReg r_srcHi, r_srcLo, r_dstHi, r_dstLo;
   5666          iselInt128Expr(&r_srcHi,&r_srcLo, env, stmt->Ist.WrTmp.data,
   5667                         IEndianess);
   5668          lookupIRTempPair( &r_dstHi, &r_dstLo, env, tmp);
   5669          addInstr(env, mk_iMOVds_RR(r_dstHi, r_srcHi) );
   5670          addInstr(env, mk_iMOVds_RR(r_dstLo, r_srcLo) );
   5671          return;
   5672       }
   5673       if (!mode64 && ty == Ity_I128) {
   5674          HReg r_srcHi, r_srcMedHi, r_srcMedLo, r_srcLo;
   5675          HReg r_dstHi, r_dstMedHi, r_dstMedLo, r_dstLo;
   5676 
   5677          iselInt128Expr_to_32x4(&r_srcHi, &r_srcMedHi,
   5678                                 &r_srcMedLo, &r_srcLo,
   5679                                 env, stmt->Ist.WrTmp.data, IEndianess);
   5680 
   5681          lookupIRTempQuad( &r_dstHi, &r_dstMedHi, &r_dstMedLo,
   5682                            &r_dstLo, env, tmp);
   5683 
   5684          addInstr(env, mk_iMOVds_RR(r_dstHi,    r_srcHi) );
   5685          addInstr(env, mk_iMOVds_RR(r_dstMedHi, r_srcMedHi) );
   5686          addInstr(env, mk_iMOVds_RR(r_dstMedLo, r_srcMedLo) );
   5687          addInstr(env, mk_iMOVds_RR(r_dstLo,    r_srcLo) );
   5688          return;
   5689       }
   5690       if (ty == Ity_I1) {
   5691          PPCCondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data,
   5692                                          IEndianess);
   5693          HReg r_dst = lookupIRTemp(env, tmp);
   5694          addInstr(env, PPCInstr_Set(cond, r_dst));
   5695          return;
   5696       }
   5697       if (ty == Ity_F64) {
   5698          HReg fr_dst = lookupIRTemp(env, tmp);
   5699          HReg fr_src = iselDblExpr(env, stmt->Ist.WrTmp.data, IEndianess);
   5700          addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
   5701          return;
   5702       }
   5703       if (ty == Ity_F32) {
   5704          HReg fr_dst = lookupIRTemp(env, tmp);
   5705          HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data, IEndianess);
   5706          addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
   5707          return;
   5708       }
   5709       if (ty == Ity_D32) {
   5710          HReg fr_dst = lookupIRTemp(env, tmp);
   5711          HReg fr_src = iselDfp32Expr(env, stmt->Ist.WrTmp.data, IEndianess);
   5712          addInstr(env, PPCInstr_Dfp64Unary(Pfp_MOV, fr_dst, fr_src));
   5713          return;
   5714       }
   5715       if (ty == Ity_V128) {
   5716          HReg v_dst = lookupIRTemp(env, tmp);
   5717          HReg v_src = iselVecExpr(env, stmt->Ist.WrTmp.data, IEndianess);
   5718          addInstr(env, PPCInstr_AvUnary(Pav_MOV, v_dst, v_src));
   5719          return;
   5720       }
   5721       if (ty == Ity_D64) {
   5722          HReg fr_dst = lookupIRTemp( env, tmp );
   5723          HReg fr_src = iselDfp64Expr( env, stmt->Ist.WrTmp.data, IEndianess );
   5724          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dst, fr_src ) );
   5725          return;
   5726       }
   5727       if (ty == Ity_D128) {
   5728          HReg fr_srcHi, fr_srcLo, fr_dstHi, fr_dstLo;
   5729 	 //         lookupDfp128IRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
   5730          lookupIRTempPair( &fr_dstHi, &fr_dstLo, env, tmp );
   5731          iselDfp128Expr( &fr_srcHi, &fr_srcLo, env, stmt->Ist.WrTmp.data,
   5732                          IEndianess );
   5733          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstHi, fr_srcHi ) );
   5734          addInstr( env, PPCInstr_Dfp64Unary( Pfp_MOV, fr_dstLo, fr_srcLo ) );
   5735          return;
   5736       }
   5737       break;
   5738    }
   5739 
   5740    /* --------- Load Linked or Store Conditional --------- */
   5741    case Ist_LLSC: {
   5742       IRTemp res    = stmt->Ist.LLSC.result;
   5743       IRType tyRes  = typeOfIRTemp(env->type_env, res);
   5744       IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
   5745 
   5746       if (stmt->Ist.LLSC.end != IEndianess)
   5747          goto stmt_fail;
   5748       if (!mode64 && (tyAddr != Ity_I32))
   5749          goto stmt_fail;
   5750       if (mode64 && (tyAddr != Ity_I64))
   5751          goto stmt_fail;
   5752 
   5753       if (stmt->Ist.LLSC.storedata == NULL) {
   5754          /* LL */
   5755          HReg r_addr = iselWordExpr_R( env, stmt->Ist.LLSC.addr, IEndianess );
   5756          HReg r_dst  = lookupIRTemp(env, res);
   5757          if (tyRes == Ity_I8) {
   5758             addInstr(env, PPCInstr_LoadL( 1, r_dst, r_addr, mode64 ));
   5759             return;
   5760          }
   5761          if (tyRes == Ity_I16) {
   5762             addInstr(env, PPCInstr_LoadL( 2, r_dst, r_addr, mode64 ));
   5763             return;
   5764          }
   5765          if (tyRes == Ity_I32) {
   5766             addInstr(env, PPCInstr_LoadL( 4, r_dst, r_addr, mode64 ));
   5767             return;
   5768          }
   5769          if (tyRes == Ity_I64 && mode64) {
   5770             addInstr(env, PPCInstr_LoadL( 8, r_dst, r_addr, mode64 ));
   5771             return;
   5772          }
   5773          /* fallthru */;
   5774       } else {
   5775          /* SC */
   5776          HReg   r_res  = lookupIRTemp(env, res); /* :: Ity_I1 */
   5777          HReg   r_a    = iselWordExpr_R(env, stmt->Ist.LLSC.addr, IEndianess);
   5778          HReg   r_src  = iselWordExpr_R(env, stmt->Ist.LLSC.storedata,
   5779                                         IEndianess);
   5780          HReg   r_tmp  = newVRegI(env);
   5781          IRType tyData = typeOfIRExpr(env->type_env,
   5782                                       stmt->Ist.LLSC.storedata);
   5783          vassert(tyRes == Ity_I1);
   5784          if (tyData == Ity_I8 || tyData == Ity_I16 || tyData == Ity_I32 ||
   5785             (tyData == Ity_I64 && mode64)) {
   5786             int size = 0;
   5787 
   5788             if (tyData == Ity_I64)
   5789                size = 8;
   5790             else if (tyData == Ity_I32)
   5791                size = 4;
   5792             else if (tyData == Ity_I16)
   5793                size = 2;
   5794             else if (tyData == Ity_I8)
   5795                size = 1;
   5796 
   5797             addInstr(env, PPCInstr_StoreC( size,
   5798                                            r_a, r_src, mode64 ));
   5799             addInstr(env, PPCInstr_MfCR( r_tmp ));
   5800             addInstr(env, PPCInstr_Shft(
   5801                              Pshft_SHR,
   5802                              env->mode64 ? False : True
   5803                                 /*F:64-bit, T:32-bit shift*/,
   5804                              r_tmp, r_tmp,
   5805                              PPCRH_Imm(False/*unsigned*/, 29)));
   5806             /* Probably unnecessary, since the IR dest type is Ity_I1,
   5807                and so we are entitled to leave whatever junk we like
   5808                drifting round in the upper 31 or 63 bits of r_res.
   5809                However, for the sake of conservativeness .. */
   5810             addInstr(env, PPCInstr_Alu(
   5811                              Palu_AND,
   5812                              r_res, r_tmp,
   5813                              PPCRH_Imm(False/*signed*/, 1)));
   5814             return;
   5815          }
   5816          /* fallthru */
   5817       }
   5818       goto stmt_fail;
   5819       /*NOTREACHED*/
   5820    }
   5821 
   5822    /* --------- Call to DIRTY helper --------- */
   5823    case Ist_Dirty: {
   5824       IRDirty* d = stmt->Ist.Dirty.details;
   5825 
   5826       /* Figure out the return type, if any. */
   5827       IRType retty = Ity_INVALID;
   5828       if (d->tmp != IRTemp_INVALID)
   5829          retty = typeOfIRTemp(env->type_env, d->tmp);
   5830 
   5831       /* Throw out any return types we don't know about.  The set of
   5832          acceptable return types is the same in both 32- and 64-bit
   5833          mode, so we don't need to inspect mode64 to make a
   5834          decision. */
   5835       Bool retty_ok = False;
   5836       switch (retty) {
   5837          case Ity_INVALID: /* function doesn't return anything */
   5838          case Ity_V128:
   5839          case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
   5840             retty_ok = True; break;
   5841          default:
   5842             break;
   5843       }
   5844       if (!retty_ok)
   5845          break; /* will go to stmt_fail: */
   5846 
   5847       /* Marshal args, do the call, clear stack, set the return value
   5848          to 0x555..555 if this is a conditional call that returns a
   5849          value and the call is skipped. */
   5850       UInt   addToSp = 0;
   5851       RetLoc rloc    = mk_RetLoc_INVALID();
   5852       doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args,
   5853                     IEndianess );
   5854       vassert(is_sane_RetLoc(rloc));
   5855 
   5856       /* Now figure out what to do with the returned value, if any. */
   5857       switch (retty) {
   5858          case Ity_INVALID: {
   5859             /* No return value.  Nothing to do. */
   5860             vassert(d->tmp == IRTemp_INVALID);
   5861             vassert(rloc.pri == RLPri_None);
   5862             vassert(addToSp == 0);
   5863             return;
   5864          }
   5865          case Ity_I32: case Ity_I16: case Ity_I8: {
   5866             /* The returned value is in %r3.  Park it in the register
   5867                associated with tmp. */
   5868             HReg r_dst = lookupIRTemp(env, d->tmp);
   5869             addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
   5870             vassert(rloc.pri == RLPri_Int);
   5871             vassert(addToSp == 0);
   5872             return;
   5873          }
   5874          case Ity_I64:
   5875             if (mode64) {
   5876                /* The returned value is in %r3.  Park it in the register
   5877                   associated with tmp. */
   5878                HReg r_dst = lookupIRTemp(env, d->tmp);
   5879                addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64)));
   5880                vassert(rloc.pri == RLPri_Int);
   5881                vassert(addToSp == 0);
   5882             } else {
   5883                /* The returned value is in %r3:%r4.  Park it in the
   5884                   register-pair associated with tmp. */
   5885                HReg r_dstHi = INVALID_HREG;
   5886                HReg r_dstLo = INVALID_HREG;
   5887                lookupIRTempPair( &r_dstHi, &r_dstLo, env, d->tmp);
   5888                addInstr(env, mk_iMOVds_RR(r_dstHi, hregPPC_GPR3(mode64)));
   5889                addInstr(env, mk_iMOVds_RR(r_dstLo, hregPPC_GPR4(mode64)));
   5890                vassert(rloc.pri == RLPri_2Int);
   5891                vassert(addToSp == 0);
   5892             }
   5893             return;
   5894          case Ity_V128: {
   5895             /* The returned value is on the stack, and *retloc tells
   5896                us where.  Fish it off the stack and then move the
   5897                stack pointer upwards to clear it, as directed by
   5898                doHelperCall. */
   5899             vassert(rloc.pri == RLPri_V128SpRel);
   5900             vassert(addToSp >= 16);
   5901             HReg      dst = lookupIRTemp(env, d->tmp);
   5902             PPCAMode* am  = PPCAMode_IR(rloc.spOff, StackFramePtr(mode64));
   5903             addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, dst, am ));
   5904             add_to_sp(env, addToSp);
   5905             return;
   5906          }
   5907          default:
   5908             /*NOTREACHED*/
   5909             vassert(0);
   5910       }
   5911    }
   5912 
   5913    /* --------- MEM FENCE --------- */
   5914    case Ist_MBE:
   5915       switch (stmt->Ist.MBE.event) {
   5916          case Imbe_Fence:
   5917             addInstr(env, PPCInstr_MFence());
   5918             return;
   5919          default:
   5920             break;
   5921       }
   5922       break;
   5923 
   5924    /* --------- INSTR MARK --------- */
   5925    /* Doesn't generate any executable code ... */
   5926    case Ist_IMark:
   5927        return;
   5928 
   5929    /* --------- ABI HINT --------- */
   5930    /* These have no meaning (denotation in the IR) and so we ignore
   5931       them ... if any actually made it this far. */
   5932    case Ist_AbiHint:
   5933        return;
   5934 
   5935    /* --------- NO-OP --------- */
   5936    /* Fairly self-explanatory, wouldn't you say? */
   5937    case Ist_NoOp:
   5938        return;
   5939 
   5940    /* --------- EXIT --------- */
   5941    case Ist_Exit: {
   5942       IRConst* dst = stmt->Ist.Exit.dst;
   5943       if (!mode64 && dst->tag != Ico_U32)
   5944          vpanic("iselStmt(ppc): Ist_Exit: dst is not a 32-bit value");
   5945       if (mode64 && dst->tag != Ico_U64)
   5946          vpanic("iselStmt(ppc64): Ist_Exit: dst is not a 64-bit value");
   5947 
   5948       PPCCondCode cc    = iselCondCode(env, stmt->Ist.Exit.guard, IEndianess);
   5949       PPCAMode*   amCIA = PPCAMode_IR(stmt->Ist.Exit.offsIP,
   5950                                       hregPPC_GPR31(mode64));
   5951 
   5952       /* Case: boring transfer to known address */
   5953       if (stmt->Ist.Exit.jk == Ijk_Boring
   5954           || stmt->Ist.Exit.jk == Ijk_Call
   5955           /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
   5956          if (env->chainingAllowed) {
   5957             /* .. almost always true .. */
   5958             /* Skip the event check at the dst if this is a forwards
   5959                edge. */
   5960             Bool toFastEP
   5961                = mode64
   5962                ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
   5963                : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
   5964             if (0) vex_printf("%s", toFastEP ? "Y" : ",");
   5965             addInstr(env, PPCInstr_XDirect(
   5966                              mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
   5967                                     : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
   5968                              amCIA, cc, toFastEP));
   5969          } else {
   5970             /* .. very occasionally .. */
   5971             /* We can't use chaining, so ask for an assisted transfer,
   5972                as that's the only alternative that is allowable. */
   5973             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst),
   5974                                     IEndianess);
   5975             addInstr(env, PPCInstr_XAssisted(r, amCIA, cc, Ijk_Boring));
   5976          }
   5977          return;
   5978       }
   5979 
   5980       /* Case: assisted transfer to arbitrary address */
   5981       switch (stmt->Ist.Exit.jk) {
   5982          /* Keep this list in sync with that in iselNext below */
   5983          case Ijk_ClientReq:
   5984          case Ijk_EmFail:
   5985          case Ijk_EmWarn:
   5986          case Ijk_NoDecode:
   5987          case Ijk_NoRedir:
   5988          case Ijk_SigBUS:
   5989          case Ijk_SigTRAP:
   5990          case Ijk_Sys_syscall:
   5991          case Ijk_InvalICache:
   5992          {
   5993             HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst),
   5994                                     IEndianess);
   5995             addInstr(env, PPCInstr_XAssisted(r, amCIA, cc,
   5996                                              stmt->Ist.Exit.jk));
   5997             return;
   5998          }
   5999          default:
   6000             break;
   6001       }
   6002 
   6003       /* Do we ever expect to see any other kind? */
   6004       goto stmt_fail;
   6005    }
   6006 
   6007    default: break;
   6008    }
   6009   stmt_fail:
   6010    ppIRStmt(stmt);
   6011    vpanic("iselStmt(ppc)");
   6012 }
   6013 
   6014 
   6015 /*---------------------------------------------------------*/
   6016 /*--- ISEL: Basic block terminators (Nexts)             ---*/
   6017 /*---------------------------------------------------------*/
   6018 
   6019 static void iselNext ( ISelEnv* env,
   6020                        IRExpr* next, IRJumpKind jk, Int offsIP,
   6021                        IREndness IEndianess)
   6022 {
   6023    if (vex_traceflags & VEX_TRACE_VCODE) {
   6024       vex_printf( "\n-- PUT(%d) = ", offsIP);
   6025       ppIRExpr( next );
   6026       vex_printf( "; exit-");
   6027       ppIRJumpKind(jk);
   6028       vex_printf( "\n");
   6029    }
   6030 
   6031    PPCCondCode always = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE );
   6032 
   6033    /* Case: boring transfer to known address */
   6034    if (next->tag == Iex_Const) {
   6035       IRConst* cdst = next->Iex.Const.con;
   6036       vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
   6037       if (jk == Ijk_Boring || jk == Ijk_Call) {
   6038          /* Boring transfer to known address */
   6039          PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
   6040          if (env->chainingAllowed) {
   6041             /* .. almost always true .. */
   6042             /* Skip the event check at the dst if this is a forwards
   6043                edge. */
   6044             Bool toFastEP
   6045                = env->mode64
   6046                ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
   6047                : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
   6048             if (0) vex_printf("%s", toFastEP ? "X" : ".");
   6049             addInstr(env, PPCInstr_XDirect(
   6050                              env->mode64 ? (Addr64)cdst->Ico.U64
   6051                                          : (Addr64)cdst->Ico.U32,
   6052                              amCIA, always, toFastEP));
   6053          } else {
   6054             /* .. very occasionally .. */
   6055             /* We can't use chaining, so ask for an assisted transfer,
   6056                as that's the only alternative that is allowable. */
   6057             HReg r = iselWordExpr_R(env, next, IEndianess);
   6058             addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
   6059                                              Ijk_Boring));
   6060          }
   6061          return;
   6062       }
   6063    }
   6064 
   6065    /* Case: call/return (==boring) transfer to any address */
   6066    switch (jk) {
   6067       case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
   6068          HReg       r     = iselWordExpr_R(env, next, IEndianess);
   6069          PPCAMode*  amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
   6070          if (env->chainingAllowed) {
   6071             addInstr(env, PPCInstr_XIndir(r, amCIA, always));
   6072          } else {
   6073             addInstr(env, PPCInstr_XAssisted(r, amCIA, always,
   6074                                              Ijk_Boring));
   6075          }
   6076          return;
   6077       }
   6078       default:
   6079          break;
   6080    }
   6081 
   6082    /* Case: assisted transfer to arbitrary address */
   6083    switch (jk) {
   6084       /* Keep this list in sync with that for Ist_Exit above */
   6085       case Ijk_ClientReq:
   6086       case Ijk_EmFail:
   6087       case Ijk_EmWarn:
   6088       case Ijk_NoDecode:
   6089       case Ijk_NoRedir:
   6090       case Ijk_SigBUS:
   6091       case Ijk_SigTRAP:
   6092       case Ijk_Sys_syscall:
   6093       case Ijk_InvalICache:
   6094       {
   6095          HReg      r     = iselWordExpr_R(env, next, IEndianess);
   6096          PPCAMode* amCIA = PPCAMode_IR(offsIP, hregPPC_GPR31(env->mode64));
   6097          addInstr(env, PPCInstr_XAssisted(r, amCIA, always, jk));
   6098          return;
   6099       }
   6100       default:
   6101          break;
   6102    }
   6103 
   6104    vex_printf( "\n-- PUT(%d) = ", offsIP);
   6105    ppIRExpr( next );
   6106    vex_printf( "; exit-");
   6107    ppIRJumpKind(jk);
   6108    vex_printf( "\n");
   6109    vassert(0); // are we expecting any other kind?
   6110 }
   6111 
   6112 
   6113 /*---------------------------------------------------------*/
   6114 /*--- Insn selector top-level                           ---*/
   6115 /*---------------------------------------------------------*/
   6116 
   6117 /* Translate an entire SB to ppc code. */
   6118 HInstrArray* iselSB_PPC ( const IRSB* bb,
   6119                           VexArch      arch_host,
   6120                           const VexArchInfo* archinfo_host,
   6121                           const VexAbiInfo*  vbi,
   6122                           Int offs_Host_EvC_Counter,
   6123                           Int offs_Host_EvC_FailAddr,
   6124                           Bool chainingAllowed,
   6125                           Bool addProfInc,
   6126                           Addr max_ga)
   6127 
   6128 {
   6129    Int       i, j;
   6130    HReg      hregLo, hregMedLo, hregMedHi, hregHi;
   6131    ISelEnv*  env;
   6132    UInt      hwcaps_host = archinfo_host->hwcaps;
   6133    Bool      mode64 = False;
   6134    UInt      mask32, mask64;
   6135    PPCAMode *amCounter, *amFailAddr;
   6136    IREndness IEndianess;
   6137 
   6138    vassert(arch_host == VexArchPPC32 || arch_host == VexArchPPC64);
   6139    mode64 = arch_host == VexArchPPC64;
   6140 
   6141    /* do some sanity checks */
   6142    mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
   6143             | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
   6144             | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
   6145 
   6146 
   6147    mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
   6148             | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
   6149             | VEX_HWCAPS_PPC64_ISA2_07;
   6150 
   6151    if (mode64) {
   6152       vassert((hwcaps_host & mask32) == 0);
   6153    } else {
   6154       vassert((hwcaps_host & mask64) == 0);
   6155    }
   6156 
   6157    /* Check that the host's endianness is as expected. */
   6158    vassert((archinfo_host->endness == VexEndnessBE) ||
   6159 	   (archinfo_host->endness == VexEndnessLE));
   6160 
   6161    if (archinfo_host->endness == VexEndnessBE)
   6162      IEndianess = Iend_BE;
   6163    else
   6164      IEndianess = Iend_LE;
   6165 
   6166    /* Make up an initial environment to use. */
   6167    env = LibVEX_Alloc_inline(sizeof(ISelEnv));
   6168    env->vreg_ctr = 0;
   6169 
   6170    /* Are we being ppc32 or ppc64? */
   6171    env->mode64 = mode64;
   6172 
   6173    /* Set up output code array. */
   6174    env->code = newHInstrArray();
   6175 
   6176    /* Copy BB's type env. */
   6177    env->type_env = bb->tyenv;
   6178 
   6179    /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
   6180     * change as we go along.
   6181     *
   6182     * vregmap2 and vregmap3 are only used in 32 bit mode
   6183     * for supporting I128 in 32-bit mode
   6184     */
   6185    env->n_vregmap = bb->tyenv->types_used;
   6186    env->vregmapLo    = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
   6187    env->vregmapMedLo = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
   6188    if (mode64) {
   6189       env->vregmapMedHi = NULL;
   6190       env->vregmapHi    = NULL;
   6191    } else {
   6192       env->vregmapMedHi = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
   6193       env->vregmapHi    = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
   6194    }
   6195 
   6196    /* and finally ... */
   6197    env->chainingAllowed = chainingAllowed;
   6198    env->max_ga          = max_ga;
   6199    env->hwcaps          = hwcaps_host;
   6200    env->previous_rm     = NULL;
   6201    env->vbi             = vbi;
   6202 
   6203    /* For each IR temporary, allocate a suitably-kinded virtual
   6204       register. */
   6205    j = 0;
   6206    for (i = 0; i < env->n_vregmap; i++) {
   6207       hregLo = hregMedLo = hregMedHi = hregHi = INVALID_HREG;
   6208       switch (bb->tyenv->types[i]) {
   6209       case Ity_I1:
   6210       case Ity_I8:
   6211       case Ity_I16:
   6212       case Ity_I32:
   6213          if (mode64) {
   6214             hregLo = mkHReg(True, HRcInt64, 0, j++);
   6215          } else {
   6216             hregLo = mkHReg(True, HRcInt32, 0, j++);
   6217          }
   6218          break;
   6219       case Ity_I64:
   6220          if (mode64) {
   6221             hregLo    = mkHReg(True, HRcInt64, 0, j++);
   6222          } else {
   6223             hregLo    = mkHReg(True, HRcInt32, 0, j++);
   6224             hregMedLo = mkHReg(True, HRcInt32, 0, j++);
   6225          }
   6226          break;
   6227       case Ity_I128:
   6228          if (mode64) {
   6229             hregLo    = mkHReg(True, HRcInt64, 0, j++);
   6230             hregMedLo = mkHReg(True, HRcInt64, 0, j++);
   6231          } else {
   6232             hregLo    = mkHReg(True, HRcInt32, 0, j++);
   6233             hregMedLo = mkHReg(True, HRcInt32, 0, j++);
   6234             hregMedHi = mkHReg(True, HRcInt32, 0, j++);
   6235             hregHi    = mkHReg(True, HRcInt32, 0, j++);
   6236          }
   6237          break;
   6238       case Ity_F32:
   6239       case Ity_F64:
   6240          hregLo = mkHReg(True, HRcFlt64, 0, j++);
   6241          break;
   6242       case Ity_V128:
   6243          hregLo = mkHReg(True, HRcVec128, 0, j++);
   6244          break;
   6245       case Ity_D32:
   6246       case Ity_D64:
   6247          hregLo = mkHReg(True, HRcFlt64, 0, j++);
   6248          break;
   6249       case Ity_D128:
   6250          hregLo    = mkHReg(True, HRcFlt64, 0, j++);
   6251          hregMedLo = mkHReg(True, HRcFlt64, 0, j++);
   6252          break;
   6253       default:
   6254          ppIRType(bb->tyenv->types[i]);
   6255          vpanic("iselBB(ppc): IRTemp type");
   6256       }
   6257       env->vregmapLo[i]    = hregLo;
   6258       env->vregmapMedLo[i] = hregMedLo;
   6259       if (!mode64) {
   6260          env->vregmapMedHi[i] = hregMedHi;
   6261          env->vregmapHi[i]    = hregHi;
   6262       }
   6263    }
   6264    env->vreg_ctr = j;
   6265 
   6266    /* The very first instruction must be an event check. */
   6267    amCounter  = PPCAMode_IR(offs_Host_EvC_Counter, hregPPC_GPR31(mode64));
   6268    amFailAddr = PPCAMode_IR(offs_Host_EvC_FailAddr, hregPPC_GPR31(mode64));
   6269    addInstr(env, PPCInstr_EvCheck(amCounter, amFailAddr));
   6270 
   6271    /* Possibly a block counter increment (for profiling).  At this
   6272       point we don't know the address of the counter, so just pretend
   6273       it is zero.  It will have to be patched later, but before this
   6274       translation is used, by a call to LibVEX_patchProfCtr. */
   6275    if (addProfInc) {
   6276       addInstr(env, PPCInstr_ProfInc());
   6277    }
   6278 
   6279    /* Ok, finally we can iterate over the statements. */
   6280    for (i = 0; i < bb->stmts_used; i++)
   6281       iselStmt(env, bb->stmts[i], IEndianess);
   6282 
   6283    iselNext(env, bb->next, bb->jumpkind, bb->offsIP, IEndianess);
   6284 
   6285    /* record the number of vregs we used. */
   6286    env->code->n_vregs = env->vreg_ctr;
   6287    return env->code;
   6288 }
   6289 
   6290 
   6291 /*---------------------------------------------------------------*/
   6292 /*--- end                                     host_ppc_isel.c ---*/
   6293 /*---------------------------------------------------------------*/
   6294