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