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