Home | History | Annotate | Download | only in priv
      1 
      2 /*---------------------------------------------------------------*/
      3 /*--- begin                                host_tilegx_isel.c ---*/
      4 /*---------------------------------------------------------------*/
      5 
      6 /*
      7   This file is part of Valgrind, a dynamic binary instrumentation
      8   framework.
      9 
     10   Copyright (C) 2010-2015 Tilera Corp.
     11 
     12   This program is free software; you can redistribute it and/or
     13   modify it under the terms of the GNU General Public License as
     14   published by the Free Software Foundation; either version 2 of the
     15   License, or (at your option) any later version.
     16 
     17   This program is distributed in the hope that it will be useful, but
     18   WITHOUT ANY WARRANTY; without even the implied warranty of
     19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20   General Public License for more details.
     21 
     22   You should have received a copy of the GNU General Public License
     23   along with this program; if not, write to the Free Software
     24   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     25   02110-1301, USA.
     26 
     27   The GNU General Public License is contained in the file COPYING.
     28 */
     29 
     30  /* Contributed by Zhi-Gang Liu <zliu at tilera dot com> */
     31 
     32 #include "libvex_basictypes.h"
     33 #include "libvex_ir.h"
     34 #include "libvex.h"
     35 
     36 #include "main_util.h"
     37 #include "main_globals.h"
     38 #include "host_generic_regs.h"
     39 #include "host_tilegx_defs.h"
     40 #include "tilegx_disasm.h"
     41 
     42 /*---------------------------------------------------------*/
     43 /*--- Register Usage Conventions                        ---*/
     44 /*---------------------------------------------------------*/
     45 
     46 /* GPR register class for tilegx */
     47 #define HRcGPR()     HRcInt64
     48 
     49 /* guest_COND offset. */
     50 #define COND_OFFSET()    (608)
     51 
     52 /*---------------------------------------------------------*/
     53 /*--- ISelEnv                                           ---*/
     54 /*---------------------------------------------------------*/
     55 
     56 /* This carries around:
     57 
     58    - A mapping from IRTemp to IRType, giving the type of any IRTemp we
     59    might encounter.  This is computed before insn selection starts,
     60    and does not change.
     61 
     62    - A mapping from IRTemp to HReg.  This tells the insn selector
     63    which virtual register(s) are associated with each IRTemp
     64    temporary.  This is computed before insn selection starts, and
     65    does not change.  We expect this mapping to map precisely the
     66    same set of IRTemps as the type mapping does.
     67 
     68    - vregmap   holds the primary register for the IRTemp.
     69    - vregmapHI holds the secondary register for the IRTemp,
     70    if any is needed.  That's only for Ity_I64 temps
     71    in 32 bit mode or Ity_I128 temps in 64-bit mode.
     72 
     73    - The name of the vreg in which we stash a copy of the link reg,
     74    so helper functions don't kill it.
     75 
     76    - The code array, that is, the insns selected so far.
     77 
     78    - A counter, for generating new virtual registers.
     79 
     80    - The host subarchitecture we are selecting insns for.
     81    This is set at the start and does not change.
     82 
     83    - A Bool to tell us if the host is 32 or 64bit.
     84    This is set at the start and does not change.
     85 
     86    - An IRExpr*, which may be NULL, holding the IR expression (an
     87    IRRoundingMode-encoded value) to which the FPU's rounding mode
     88    was most recently set.  Setting to NULL is always safe.  Used to
     89    avoid redundant settings of the FPU's rounding mode, as
     90    described in set_FPU_rounding_mode below.
     91 
     92    - A VexMiscInfo*, needed for knowing how to generate
     93    function calls for this target
     94 */
     95 typedef struct {
     96   IRTypeEnv *type_env;
     97 
     98   HReg *vregmap;
     99 
    100   Int n_vregmap;
    101 
    102   HInstrArray *code;
    103 
    104   Int vreg_ctr;
    105 
    106   UInt hwcaps;
    107 
    108   Bool mode64;
    109 
    110   Bool   chainingAllowed;
    111 
    112   Addr64 max_ga;
    113 
    114   IRExpr *previous_rm;
    115 
    116   VexAbiInfo *vbi;
    117 } ISelEnv;
    118 
    119 static HReg lookupIRTemp ( ISelEnv * env, IRTemp tmp )
    120 {
    121   vassert(tmp >= 0);
    122   vassert(tmp < env->n_vregmap);
    123   return env->vregmap[tmp];
    124 }
    125 
    126 static void addInstr ( ISelEnv * env, TILEGXInstr * instr )
    127 {
    128   addHInstr(env->code, instr);
    129   if (vex_traceflags & VEX_TRACE_VCODE) {
    130     ppTILEGXInstr(instr);
    131     vex_printf("\n");
    132   }
    133 }
    134 
    135 static HReg newVRegI ( ISelEnv * env )
    136 {
    137   HReg reg = mkHReg(True /*virtual R*/, HRcGPR(), 0, env->vreg_ctr);
    138   env->vreg_ctr++;
    139   return reg;
    140 }
    141 
    142 /*---------------------------------------------------------*/
    143 /*--- ISEL: Forward declarations                        ---*/
    144 /*---------------------------------------------------------*/
    145 
    146 /* These are organised as iselXXX and iselXXX_wrk pairs.  The
    147    iselXXX_wrk do the real work, but are not to be called directly.
    148    For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
    149    checks that all returned registers are virtual.  You should not
    150    call the _wrk version directly.
    151 */
    152 /* Compute an I8/I16/I32/I64 into a RH (reg-or-halfword-immediate).
    153    It's important to specify whether the immediate is to be regarded
    154    as signed or not.  If yes, this will never return -32768 as an
    155    immediate; this guaranteed that all signed immediates that are
    156    return can have their sign inverted if need be.
    157 */
    158 static TILEGXRH *iselWordExpr_RH_wrk ( ISelEnv * env, Bool syned, IRExpr * e );
    159 static TILEGXRH *iselWordExpr_RH ( ISelEnv * env, Bool syned, IRExpr * e );
    160 
    161 static TILEGXRH *iselWordExpr_RH6u_wrk ( ISelEnv * env, IRExpr * e );
    162 static TILEGXRH *iselWordExpr_RH6u ( ISelEnv * env, IRExpr * e );
    163 
    164 /* compute an I8/I16/I32/I64 into a GPR*/
    165 static HReg iselWordExpr_R_wrk ( ISelEnv * env, IRExpr * e );
    166 static HReg iselWordExpr_R ( ISelEnv * env, IRExpr * e );
    167 
    168 /* compute an I64 into an AMode. */
    169 static TILEGXAMode *iselWordExpr_AMode_wrk ( ISelEnv * env, IRExpr * e,
    170                                              IRType xferTy );
    171 static TILEGXAMode *iselWordExpr_AMode ( ISelEnv * env, IRExpr * e,
    172                                          IRType xferTy );
    173 
    174 static TILEGXCondCode iselCondCode_wrk ( ISelEnv * env, IRExpr * e );
    175 static TILEGXCondCode iselCondCode ( ISelEnv * env, IRExpr * e );
    176 
    177 /*---------------------------------------------------------*/
    178 /*--- ISEL: Misc helpers                                ---*/
    179 /*---------------------------------------------------------*/
    180 
    181 /* Make an int reg-reg move. */
    182 static TILEGXInstr *mk_iMOVds_RR ( HReg r_dst, HReg r_src )
    183 {
    184   vassert(hregClass(r_dst) == hregClass(r_src));
    185   vassert(hregClass(r_src) == HRcInt32 || hregClass(r_src) == HRcInt64);
    186   return TILEGXInstr_Alu(GXalu_OR, r_dst, r_src, TILEGXRH_Reg(r_src));
    187 }
    188 
    189 /*---------------------------------------------------------*/
    190 /*--- ISEL: Function call helpers                       ---*/
    191 /*---------------------------------------------------------*/
    192 
    193 /* Used only in doHelperCall. See big comment in doHelperCall
    194    handling of register-parameter args.  This function figures out
    195    whether evaluation of an expression might require use of a fixed
    196    register.
    197 */
    198 static Bool mightRequireFixedRegs ( IRExpr * e )
    199 {
    200   switch (e->tag) {
    201   case Iex_RdTmp:
    202   case Iex_Const:
    203   case Iex_Get:
    204     return False;
    205   default:
    206     return True;
    207   }
    208 }
    209 
    210 /* Do a complete function call.  guard is a Ity_Bit expression
    211    indicating whether or not the call happens.  If guard==NULL, the
    212    call is unconditional. */
    213 
    214 static void doHelperCall ( ISelEnv * env, IRExpr * guard, IRCallee * cee,
    215                            IRExpr ** args, IRType retTy )
    216 {
    217   TILEGXCondCode cc;
    218   HReg argregs[TILEGX_N_REGPARMS];
    219   HReg tmpregs[TILEGX_N_REGPARMS];
    220   Bool go_fast;
    221   Long  n_args, i, argreg;
    222   ULong argiregs;
    223   ULong target;
    224   HReg src = INVALID_HREG;
    225 
    226 
    227   UInt nVECRETs = 0;
    228   UInt nBBPTRs  = 0;
    229 
    230   /* TILEGX calling convention: up to 10 registers (r0 ... r9)
    231      are allowed to be used for passing integer arguments. They correspond
    232      to regs GPR0 ... GPR9. */
    233 
    234   /* Note that the cee->regparms field is meaningless on ARM64 hosts
    235      (since there is only one calling convention) and so we always
    236      ignore it. */
    237 
    238   n_args = 0;
    239   for (i = 0; args[i]; i++) {
    240     n_args++;
    241     IRExpr* arg = args[i];
    242     if (UNLIKELY(arg->tag == Iex_VECRET)) {
    243       nVECRETs++;
    244     } else if (UNLIKELY(arg->tag == Iex_BBPTR)) {
    245       nBBPTRs++;
    246     }
    247   }
    248 
    249   if (nVECRETs || nBBPTRs)
    250     vex_printf("nVECRETs=%u, nBBPTRs=%u\n",
    251                nVECRETs, nBBPTRs);
    252 
    253   if (TILEGX_N_REGPARMS < n_args) {
    254     vpanic("doHelperCall(TILEGX): cannot currently handle > 10 args");
    255   }
    256   argregs[0] = hregTILEGX_R0();
    257   argregs[1] = hregTILEGX_R1();
    258   argregs[2] = hregTILEGX_R2();
    259   argregs[3] = hregTILEGX_R3();
    260   argregs[4] = hregTILEGX_R4();
    261   argregs[5] = hregTILEGX_R5();
    262   argregs[6] = hregTILEGX_R6();
    263   argregs[7] = hregTILEGX_R7();
    264   argregs[8] = hregTILEGX_R8();
    265   argregs[9] = hregTILEGX_R9();
    266   argiregs = 0;
    267 
    268   for (i = 0; i < TILEGX_N_REGPARMS; i++)
    269     tmpregs[i] = INVALID_HREG;
    270 
    271   /* First decide which scheme (slow or fast) is to be used.  First
    272      assume the fast scheme, and select slow if any contraindications
    273      (wow) appear. */
    274 
    275   go_fast = True;
    276 
    277   if (guard) {
    278     if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
    279         && guard->Iex.Const.con->Ico.U1 == True) {
    280       /* unconditional */
    281     } else {
    282       /* Not manifestly unconditional -- be conservative. */
    283       go_fast = False;
    284     }
    285   }
    286 
    287   if (go_fast) {
    288     for (i = 0; i < n_args; i++) {
    289       if (mightRequireFixedRegs(args[i])) {
    290         go_fast = False;
    291         break;
    292       }
    293     }
    294   }
    295 
    296   /* At this point the scheme to use has been established.  Generate
    297      code to get the arg values into the argument rregs. */
    298   if (go_fast) {
    299     /* FAST SCHEME */
    300     argreg = 0;
    301 
    302     for (i = 0; i < n_args; i++) {
    303       vassert(argreg < TILEGX_N_REGPARMS);
    304       vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32 ||
    305               typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
    306 
    307       argiregs |= (1 << (argreg));
    308       addInstr(env, mk_iMOVds_RR(argregs[argreg],
    309                                  iselWordExpr_R(env,
    310                                                 args[i])));
    311       argreg++;
    312     }
    313     /* Fast scheme only applies for unconditional calls.  Hence: */
    314     cc = TILEGXcc_AL;
    315   } else {
    316     /* SLOW SCHEME; move via temporaries */
    317     argreg = 0;
    318 
    319     for (i = 0; i < n_args; i++) {
    320       vassert(argreg < TILEGX_N_REGPARMS);
    321       vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32
    322               || typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
    323       tmpregs[argreg] = iselWordExpr_R(env, args[i]);
    324       argreg++;
    325     }
    326 
    327     /* Now we can compute the condition.  We can't do it earlier
    328        because the argument computations could trash the condition
    329        codes.  Be a bit clever to handle the common case where the
    330        guard is 1:Bit. */
    331     cc = TILEGXcc_AL;
    332     if (guard) {
    333       if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
    334           && guard->Iex.Const.con->Ico.U1 == True) {
    335         /* unconditional -- do nothing */
    336       } else {
    337         cc = iselCondCode(env, guard);
    338         src = iselWordExpr_R(env, guard);
    339       }
    340     }
    341     /* Move the args to their final destinations. */
    342     for (i = 0; i < argreg; i++) {
    343       if (hregIsInvalid(tmpregs[i]))  // Skip invalid regs
    344         continue;
    345       /* None of these insns, including any spill code that might
    346          be generated, may alter the condition codes. */
    347       argiregs |= (1 << (i));
    348       addInstr(env, mk_iMOVds_RR(argregs[i], tmpregs[i]));
    349     }
    350   }
    351 
    352   target = (Addr)(cee->addr);
    353 
    354   /* Finally, the call itself. */
    355   if (cc == TILEGXcc_AL)
    356     addInstr(env, TILEGXInstr_CallAlways(cc, target, argiregs));
    357   else
    358     addInstr(env, TILEGXInstr_Call(cc, target, argiregs, src));
    359 }
    360 
    361 /*---------------------------------------------------------*/
    362 /*--- ISEL: Integer expression auxiliaries              ---*/
    363 /*---------------------------------------------------------*/
    364 
    365 /* --------------------- AMODEs --------------------- */
    366 
    367 /* Return an AMode which computes the value of the specified
    368    expression, possibly also adding insns to the code list as a
    369    result.  The expression may only be a word-size one.
    370 */
    371 
    372 static Bool uInt_fits_in_16_bits ( UInt u )
    373 {
    374    UInt v = u & 0xFFFF;
    375 
    376    v = (Int)(v << 16) >> 16;   /* sign extend */
    377 
    378    return u == v;
    379 }
    380 
    381 static Bool sane_AMode ( ISelEnv * env, TILEGXAMode * am )
    382 {
    383   if (am->tag == GXam_IR)
    384     return toBool(hregClass(am->GXam.IR.base) == HRcGPR() &&
    385                   hregIsVirtual(am->GXam.IR.base) &&
    386                   uInt_fits_in_16_bits(am->GXam.IR.index));
    387 
    388   vpanic("sane_AMode: unknown tilegx amode tag");
    389 }
    390 
    391 static TILEGXAMode *iselWordExpr_AMode ( ISelEnv * env, IRExpr * e,
    392                                          IRType xferTy )
    393 {
    394   TILEGXAMode *am = iselWordExpr_AMode_wrk(env, e, xferTy);
    395   vassert(sane_AMode(env, am));
    396   return am;
    397 }
    398 
    399 /* DO NOT CALL THIS DIRECTLY ! */
    400 static TILEGXAMode *iselWordExpr_AMode_wrk ( ISelEnv * env, IRExpr * e,
    401                                              IRType xferTy )
    402 {
    403   IRType ty = typeOfIRExpr(env->type_env, e);
    404 
    405   vassert(ty == Ity_I64);
    406   /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
    407   if (e->tag == Iex_Binop
    408       && e->Iex.Binop.op == Iop_Add64
    409       && e->Iex.Binop.arg2->tag == Iex_Const
    410       && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
    411       && uInt_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)) {
    412 
    413     return TILEGXAMode_IR((Long) e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
    414                           iselWordExpr_R(env, e->Iex.Binop.arg1));
    415   }
    416 
    417   /* Doesn't match anything in particular.  Generate it into
    418      a register and use that. */
    419   return TILEGXAMode_IR(0, iselWordExpr_R(env, e));
    420 }
    421 
    422 
    423 
    424 
    425 
    426 /*---------------------------------------------------------*/
    427 /*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
    428 /*---------------------------------------------------------*/
    429 
    430 /* Select insns for an integer-typed expression, and add them to the
    431    code list.  Return a reg holding the result.  This reg will be a
    432    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
    433    want to modify it, ask for a new vreg, copy it in there, and modify
    434    the copy.  The register allocator will do its best to map both
    435    add vregs to the same real register, so the copies will often disappear
    436    later in the game.
    437 
    438    This should handle expressions of 64, 32, 16 and 8-bit type.
    439    All results are returned in a  64bit register.
    440 */
    441 static HReg iselWordExpr_R ( ISelEnv * env, IRExpr * e )
    442 {
    443   HReg r = iselWordExpr_R_wrk(env, e);
    444   /* sanity checks ... */
    445 
    446   vassert(hregClass(r) == HRcGPR());
    447   vassert(hregIsVirtual(r));
    448   return r;
    449 }
    450 
    451 /* DO NOT CALL THIS DIRECTLY ! */
    452 static HReg iselWordExpr_R_wrk ( ISelEnv * env, IRExpr * e )
    453 {
    454   IRType ty = typeOfIRExpr(env->type_env, e);
    455   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
    456           ty == Ity_I1 || ty == Ity_I64);
    457 
    458   switch (e->tag) {
    459     /* --------- TEMP --------- */
    460   case Iex_RdTmp:
    461     return lookupIRTemp(env, e->Iex.RdTmp.tmp);
    462 
    463     /* --------- LOAD --------- */
    464   case Iex_Load: {
    465     HReg r_dst = newVRegI(env);
    466     TILEGXAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
    467 
    468     if (e->Iex.Load.end != Iend_LE
    469         && e->Iex.Load.end != Iend_BE)
    470       goto irreducible;
    471 
    472     addInstr(env, TILEGXInstr_Load(toUChar(sizeofIRType(ty)),
    473                                    r_dst, am_addr));
    474     return r_dst;
    475     break;
    476   }
    477     /* --------- BINARY OP --------- */
    478   case Iex_Binop: {
    479     TILEGXAluOp aluOp;
    480     TILEGXShftOp shftOp;
    481 
    482     switch (e->Iex.Binop.op) {
    483 
    484     case Iop_Add8:
    485     case Iop_Add16:
    486     case Iop_Add32:
    487     case Iop_Add64:
    488       aluOp = GXalu_ADD;
    489       break;
    490 
    491     case Iop_Sub8:
    492     case Iop_Sub16:
    493     case Iop_Sub32:
    494     case Iop_Sub64:
    495       aluOp = GXalu_SUB;
    496       break;
    497 
    498     case Iop_And8:
    499     case Iop_And16:
    500     case Iop_And32:
    501     case Iop_And64:
    502       aluOp = GXalu_AND;
    503       break;
    504 
    505     case Iop_Or8:
    506     case Iop_Or16:
    507     case Iop_Or32:
    508     case Iop_Or64:
    509       aluOp = GXalu_OR;
    510       break;
    511 
    512     case Iop_Xor8:
    513     case Iop_Xor16:
    514     case Iop_Xor32:
    515     case Iop_Xor64:
    516       aluOp = GXalu_XOR;
    517       break;
    518 
    519     default:
    520       aluOp = GXalu_INVALID;
    521       break;
    522     }
    523 
    524     /* For commutative ops we assume any literal
    525        values are on the second operand. */
    526     if (aluOp != GXalu_INVALID) {
    527       HReg r_dst = newVRegI(env);
    528       HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    529       TILEGXRH *ri_srcR = NULL;
    530       /* get right arg into an RH, in the appropriate way */
    531       switch (aluOp) {
    532       case GXalu_ADD:
    533       case GXalu_SUB:
    534         ri_srcR = iselWordExpr_RH(env, True /*signed */ ,
    535                                   e->Iex.Binop.arg2);
    536         break;
    537       case GXalu_AND:
    538       case GXalu_OR:
    539       case GXalu_XOR:
    540         ri_srcR = iselWordExpr_RH(env, True /*signed */,
    541                                   e->Iex.Binop.arg2);
    542         break;
    543       default:
    544         vpanic("iselWordExpr_R_wrk-aluOp-arg2");
    545       }
    546       addInstr(env, TILEGXInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
    547       return r_dst;
    548     }
    549 
    550     /* a shift? */
    551     switch (e->Iex.Binop.op) {
    552     case Iop_Shl32:
    553     case Iop_Shl64:
    554       shftOp = GXshft_SLL;
    555       break;
    556     case Iop_Shr32:
    557     case Iop_Shr64:
    558       shftOp = GXshft_SRL;
    559       break;
    560     case Iop_Sar64:
    561       shftOp = GXshft_SRA;
    562       break;
    563     case Iop_Shl8x8:
    564       shftOp = GXshft_SLL8x8;
    565       break;
    566     case Iop_Shr8x8:
    567       shftOp = GXshft_SRL8x8;
    568       break;
    569     default:
    570       shftOp = GXshft_INVALID;
    571       break;
    572     }
    573 
    574     /* we assume any literal values are on the second operand. */
    575     if (shftOp != GXshft_INVALID) {
    576       HReg r_dst = newVRegI(env);
    577       HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    578       TILEGXRH *ri_srcR = NULL;
    579       /* get right arg into an RH, in the appropriate way */
    580       switch (shftOp) {
    581       case GXshft_SLL:
    582       case GXshft_SRL:
    583       case GXshft_SRA:
    584         //ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
    585         //break;
    586       case GXshft_SLL8x8:
    587       case GXshft_SRL8x8:
    588         //if (e->Iex.Binop.arg2->tag == GXrh_Imm)
    589         //{
    590         // ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
    591         //  break;
    592         //}
    593         ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
    594         break;
    595       default:
    596         vpanic("iselIntExpr_R_wrk-shftOp-arg2");
    597       }
    598       /* widen the left arg if needed */
    599       /*TODO do we need this? */
    600       if (ty == Ity_I8 || ty == Ity_I16)
    601         goto irreducible;
    602       if (ty == Ity_I64) {
    603         addInstr(env, TILEGXInstr_Shft(shftOp, False/*64bit shift */,
    604                                        r_dst, r_srcL, ri_srcR));
    605       } else {
    606         addInstr(env, TILEGXInstr_Shft(shftOp, True /*32bit shift */,
    607                                        r_dst, r_srcL, ri_srcR));
    608       }
    609       return r_dst;
    610     }
    611 
    612     /* Cmp*32*(x,y) ? */
    613     if (e->Iex.Binop.op == Iop_CasCmpEQ32
    614         || e->Iex.Binop.op == Iop_CmpEQ32
    615         || e->Iex.Binop.op == Iop_CasCmpNE32
    616         || e->Iex.Binop.op == Iop_CmpNE32
    617         || e->Iex.Binop.op == Iop_CmpNE64
    618         || e->Iex.Binop.op == Iop_CmpLT32S
    619         || e->Iex.Binop.op == Iop_CmpLT32U
    620         || e->Iex.Binop.op == Iop_CmpLT64U
    621         || e->Iex.Binop.op == Iop_CmpLE32S
    622         || e->Iex.Binop.op == Iop_CmpLE64S
    623         || e->Iex.Binop.op == Iop_CmpLE64U
    624         || e->Iex.Binop.op == Iop_CmpLT64S
    625         || e->Iex.Binop.op == Iop_CmpEQ64
    626         || e->Iex.Binop.op == Iop_CasCmpEQ64
    627         || e->Iex.Binop.op == Iop_CasCmpNE64) {
    628 
    629       Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
    630                     || e->Iex.Binop.op == Iop_CmpLE32S
    631                     || e->Iex.Binop.op == Iop_CmpLT64S
    632                     || e->Iex.Binop.op == Iop_CmpLE64S);
    633       Bool size32;
    634       HReg dst = newVRegI(env);
    635       HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
    636       HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
    637       TILEGXCondCode cc;
    638 
    639       switch (e->Iex.Binop.op) {
    640       case Iop_CasCmpEQ32:
    641       case Iop_CmpEQ32:
    642         cc = TILEGXcc_EQ;
    643         size32 = True;
    644         break;
    645       case Iop_CasCmpNE32:
    646       case Iop_CmpNE32:
    647         cc = TILEGXcc_NE;
    648         size32 = True;
    649         break;
    650       case Iop_CasCmpNE64:
    651       case Iop_CmpNE64:
    652         cc = TILEGXcc_NE;
    653         size32 = True;
    654         break;
    655       case Iop_CmpLT32S:
    656         cc = TILEGXcc_LT;
    657         size32 = True;
    658         break;
    659       case Iop_CmpLT32U:
    660         cc = TILEGXcc_LO;
    661         size32 = True;
    662         break;
    663       case Iop_CmpLT64U:
    664         cc = TILEGXcc_LT;
    665         size32 = False;
    666         break;
    667       case Iop_CmpLE32S:
    668         cc = TILEGXcc_LE;
    669         size32 = True;
    670         break;
    671       case Iop_CmpLE64S:
    672         cc = TILEGXcc_LE;
    673         size32 = False;
    674         break;
    675       case Iop_CmpLE64U:
    676         cc = TILEGXcc_LE;
    677         size32 = False;
    678         break;
    679       case Iop_CmpLT64S:
    680         cc = TILEGXcc_LT;
    681         size32 = False;
    682         break;
    683       case Iop_CasCmpEQ64:
    684       case Iop_CmpEQ64:
    685         cc = TILEGXcc_EQ;
    686         size32 = False;
    687         break;
    688       default:
    689         vpanic
    690           ("iselCondCode(tilegx): CmpXX32 or CmpXX64");
    691       }
    692 
    693       addInstr(env, TILEGXInstr_Cmp(syned, size32, dst, r1, r2, cc));
    694       return dst;
    695 
    696       break;
    697 
    698     }
    699 
    700     if (e->Iex.Binop.op == Iop_CmpEQ8x8) {
    701 
    702       Bool syned = False;
    703 
    704       Bool size32;
    705       HReg dst = newVRegI(env);
    706       HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
    707       TILEGXRH *r2 = iselWordExpr_RH(env, True, e->Iex.Binop.arg2);
    708       TILEGXCondCode cc;
    709 
    710       switch (e->Iex.Binop.op) {
    711       case Iop_CmpEQ8x8:
    712         cc = TILEGXcc_EQ8x8;
    713         size32 = False;
    714         break;
    715 
    716       default:
    717         vassert(0);
    718       }
    719 
    720       addInstr(env, TILEGXInstr_CmpI(syned, size32, dst, r1, r2, cc));
    721       return dst;
    722 
    723       break;
    724     }
    725 
    726     if (e->Iex.Binop.op == Iop_Max32U) {
    727       /*
    728         tmp = argL - argR;
    729         tmp &= (1<<31)
    730         dst = (tmp) ? (argL) ? (argR)
    731       */
    732       HReg argL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    733       TILEGXRH *argR = iselWordExpr_RH(env, False /*signed */ ,
    734                                        e->Iex.Binop.arg2);
    735       HReg dst = newVRegI(env);
    736       HReg tmp = newVRegI(env);
    737       // temp = argL - argR
    738       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, tmp, argL, argR));
    739       // tmp &= bit31
    740       addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, tmp, tmp , 31, 31));
    741       // (tmp == 0) ? (argL) : (argR)
    742       addInstr(env, TILEGXInstr_MovCond(dst, argL, argR, tmp, TILEGXcc_EZ));
    743       return dst;
    744     }
    745 
    746     if (e->Iex.Binop.op == Iop_MullS32 || e->Iex.Binop.op == Iop_MullU32) {
    747       Bool syned = (e->Iex.Binop.op == Iop_MullS32);
    748       Bool sz32 = (e->Iex.Binop.op == Iop_Mul32);
    749       HReg r_dst = newVRegI(env);
    750       HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
    751       HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
    752       addInstr(env, TILEGXInstr_Mul(syned /*Unsigned or Signed */ ,
    753                                     True /*widen */ ,
    754                                     sz32 /*32bit or 64bit */,
    755                                     r_dst, r_srcL, r_srcR));
    756       return r_dst;
    757     }
    758 
    759     if (e->Iex.Binop.op == Iop_32HLto64) {
    760       HReg tHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
    761       HReg tLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
    762       HReg tLo_1 = newVRegI(env);
    763       HReg tHi_1 = newVRegI(env);
    764       HReg r_dst = newVRegI(env);
    765       HReg mask = newVRegI(env);
    766 
    767       addInstr(env, TILEGXInstr_Shft(GXshft_SLL, False, tHi_1, tHi,
    768                                      TILEGXRH_Imm(False, 32)));
    769 
    770       addInstr(env, TILEGXInstr_LI(mask, 0xffffffff));
    771       addInstr(env, TILEGXInstr_Alu(GXalu_AND, tLo_1, tLo,
    772                                     TILEGXRH_Reg(mask)));
    773       addInstr(env, TILEGXInstr_Alu(GXalu_OR, r_dst, tHi_1,
    774                                     TILEGXRH_Reg(tLo_1)));
    775 
    776       return r_dst;
    777     }
    778 
    779     /* Anything reached here !*/
    780     goto irreducible;
    781   }
    782 
    783     /* --------- UNARY OP --------- */
    784   case Iex_Unop: {
    785 
    786     IROp op_unop = e->Iex.Unop.op;
    787 
    788     switch (op_unop) {
    789     case Iop_Not1: {
    790       HReg r_dst = newVRegI(env);
    791       HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
    792       TILEGXRH *r_srcR = TILEGXRH_Reg(r_srcL);
    793 
    794       addInstr(env, TILEGXInstr_LI(r_dst, 0x1));
    795       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, r_dst, r_dst, r_srcR));
    796       return r_dst;
    797     }
    798 
    799     case Iop_Not8:
    800     case Iop_Not16:
    801     case Iop_Not32:
    802     case Iop_Not64: {
    803       /* not x = nor x, x */
    804       HReg r_dst = newVRegI(env);
    805       HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
    806       TILEGXRH *r_srcR = TILEGXRH_Reg(r_srcL);
    807 
    808       addInstr(env, TILEGXInstr_Alu(GXalu_NOR, r_dst, r_srcL, r_srcR));
    809       return r_dst;
    810     }
    811 
    812     case Iop_CmpNEZ8x8: {
    813 
    814       Bool syned = False;
    815       Bool size32;
    816       HReg dst = newVRegI(env);
    817       HReg r1;
    818       TILEGXCondCode cc =  TILEGXcc_NE8x8;
    819       size32 = False;
    820       r1 = iselWordExpr_R(env, e->Iex.Unop.arg);
    821       addInstr(env, TILEGXInstr_CmpI(syned, size32, dst, hregTILEGX_R63(),
    822                                      TILEGXRH_Reg(r1), cc));
    823 
    824       return dst;
    825       break;
    826     }
    827 
    828     case Iop_16to8:
    829     case Iop_32to8:
    830     case Iop_64to8:
    831     case Iop_32to16:
    832     case Iop_64to16:
    833     case Iop_64to32:
    834     case Iop_128to64:
    835 
    836       return iselWordExpr_R(env, e->Iex.Unop.arg);
    837 
    838     case Iop_1Uto64:
    839     case Iop_1Uto32:
    840     case Iop_1Uto8: {
    841       HReg dst = newVRegI(env);
    842       HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
    843       addInstr(env, TILEGXInstr_Alu(GXalu_AND, dst, src, TILEGXRH_Imm(False, 1)));
    844       return dst;
    845     }
    846     case Iop_8Uto16:
    847     case Iop_8Uto32:
    848     case Iop_8Uto64:
    849     case Iop_16Uto32:
    850     case Iop_16Uto64: {
    851 
    852       HReg dst     = newVRegI(env);
    853       HReg src     = iselWordExpr_R(env, e->Iex.Unop.arg);
    854       Bool srcIs16 = toBool( e->Iex.Unop.op==Iop_16Uto32
    855                              || e->Iex.Unop.op==Iop_16Uto64 );
    856 
    857       addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, dst, src,
    858                                    0,
    859                                    srcIs16 ? 15 : 7));
    860 
    861       return dst;
    862     }
    863 
    864     case Iop_32to1:
    865     case Iop_64to1:
    866       {
    867         HReg r_dst = newVRegI(env);
    868         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    869 
    870         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_dst, r_src, 0, 0));
    871         return r_dst;
    872       }
    873     case Iop_1Sto32:
    874     case Iop_1Sto64:
    875       {
    876         HReg r_dst = newVRegI(env);
    877         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    878 
    879         addInstr(env, TILEGXInstr_Bf(GXbf_EXTS, r_dst, r_src, 0, 0));
    880         return r_dst;
    881       }
    882     case Iop_8Sto16:
    883     case Iop_8Sto32:
    884     case Iop_8Sto64:
    885       {
    886         HReg r_dst = newVRegI(env);
    887         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    888 
    889         addInstr(env, TILEGXInstr_Bf(GXbf_EXTS, r_dst, r_src, 0, 7));
    890         return r_dst;
    891       }
    892     case Iop_16Sto32:
    893     case Iop_16Sto64:
    894       {
    895         HReg r_dst = newVRegI(env);
    896         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    897 
    898         addInstr(env, TILEGXInstr_Bf(GXbf_EXTS, r_dst, r_src, 0, 15));
    899         return r_dst;
    900       }
    901     case Iop_32Uto64:
    902       {
    903         HReg r_dst = newVRegI(env);
    904         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    905 
    906         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_dst, r_src, 0, 31));
    907         return r_dst;
    908       }
    909     case Iop_32Sto64:
    910       {
    911         HReg r_dst = newVRegI(env);
    912         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    913 
    914         addInstr(env, TILEGXInstr_Bf(GXbf_EXTS, r_dst, r_src, 0, 31));
    915         return r_dst;
    916       }
    917 
    918     case Iop_CmpNEZ8: {
    919       HReg r_dst = newVRegI(env);
    920       HReg tmp = newVRegI(env);
    921       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    922 
    923       TILEGXCondCode cc;
    924 
    925       cc = TILEGXcc_NE;
    926       addInstr(env, TILEGXInstr_Alu(GXalu_AND, tmp, r_src,
    927                                     TILEGXRH_Imm(False, 0xFF)));
    928       addInstr(env, TILEGXInstr_Cmp(False, True, r_dst, tmp,
    929                                     hregTILEGX_R63(), cc));
    930       return r_dst;
    931     }
    932 
    933     case Iop_CmpNEZ32: {
    934       HReg r_dst = newVRegI(env);
    935       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    936 
    937       TILEGXCondCode cc;
    938 
    939       cc = TILEGXcc_NE;
    940 
    941       addInstr(env, TILEGXInstr_Cmp(False, True, r_dst, r_src,
    942                                     hregTILEGX_R63(), cc));
    943       return r_dst;
    944     }
    945 
    946     case Iop_CmpwNEZ32: {
    947       HReg r_dst = newVRegI(env);
    948       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    949 
    950       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, r_dst, hregTILEGX_R63(),
    951                                     TILEGXRH_Reg(r_src)));
    952 
    953       addInstr(env, TILEGXInstr_Alu(GXalu_OR, r_dst, r_dst,
    954                                     TILEGXRH_Reg(r_src)));
    955       addInstr(env, TILEGXInstr_Shft(GXshft_SRA, True, r_dst, r_dst,
    956                                      TILEGXRH_Imm(False, 31)));
    957       return r_dst;
    958     }
    959 
    960     case Iop_Left8:
    961     case Iop_Left16:
    962     case Iop_Left32:
    963     case Iop_Left64: {
    964 
    965       HReg r_dst = newVRegI(env);
    966       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    967       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, r_dst, hregTILEGX_R63(),
    968                                     TILEGXRH_Reg(r_src)));
    969       addInstr(env, TILEGXInstr_Alu(GXalu_OR, r_dst, r_dst,
    970                                     TILEGXRH_Reg(r_src)));
    971       return r_dst;
    972     }
    973 
    974     case Iop_Ctz64:
    975     case Iop_Clz64: {
    976       HReg r_dst = newVRegI(env);
    977       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    978       if (op_unop == Iop_Clz64)
    979         addInstr(env, TILEGXInstr_Unary(GXun_CLZ, r_dst, r_src));
    980       else
    981         addInstr(env, TILEGXInstr_Unary(GXun_CTZ, r_dst, r_src));
    982       return r_dst;
    983     }
    984 
    985     case Iop_CmpNEZ64: {
    986 
    987       HReg r_dst = newVRegI(env);
    988       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
    989 
    990       TILEGXCondCode cc;
    991 
    992       cc = TILEGXcc_NE;
    993 
    994       addInstr(env, TILEGXInstr_Cmp(False, False, r_dst, r_src,
    995                                     hregTILEGX_R63(), cc));
    996       return r_dst;
    997     }
    998 
    999     case Iop_CmpwNEZ64: {
   1000       HReg tmp1;
   1001       HReg tmp2 = newVRegI(env);
   1002 
   1003       tmp1 = iselWordExpr_R(env, e->Iex.Unop.arg);
   1004 
   1005       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, tmp2, hregTILEGX_R63(),
   1006                                     TILEGXRH_Reg(tmp1)));
   1007 
   1008       addInstr(env, TILEGXInstr_Alu(GXalu_OR, tmp2, tmp2, TILEGXRH_Reg(tmp1)));
   1009       addInstr(env, TILEGXInstr_Shft(GXshft_SRA, False, tmp2, tmp2,
   1010                                      TILEGXRH_Imm (False, 63)));
   1011       return tmp2;
   1012     }
   1013 
   1014     default:
   1015       goto irreducible;
   1016       break;
   1017     }
   1018     break;
   1019   }
   1020 
   1021     /* --------- GET --------- */
   1022   case Iex_Get: {
   1023     if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32
   1024         || ((ty == Ity_I64))) {
   1025       HReg r_dst;
   1026       TILEGXAMode *am_addr;
   1027       r_dst = newVRegI(env);
   1028       am_addr = TILEGXAMode_IR(e->Iex.Get.offset,
   1029                                TILEGXGuestStatePointer());
   1030       addInstr(env, TILEGXInstr_Load(toUChar(sizeofIRType(ty)),
   1031                                      r_dst, am_addr));
   1032       return r_dst;
   1033     }
   1034   }
   1035 
   1036     /* --------- ITE --------- */
   1037   case Iex_ITE: {
   1038     if ((ty == Ity_I8 || ty == Ity_I16 ||
   1039          ty == Ity_I32 || ((ty == Ity_I64))) &&
   1040         typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
   1041 
   1042       HReg r0 = iselWordExpr_R(env, e->Iex.ITE.iffalse);
   1043       HReg r1 = iselWordExpr_R(env, e->Iex.ITE.iftrue);
   1044       HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
   1045       HReg r_dst = newVRegI(env);
   1046 
   1047       /* r_dst = (r_cond) ? r1 : r0 */
   1048 
   1049       addInstr(env, TILEGXInstr_MovCond(r_dst, r0, TILEGXRH_Reg(r1),
   1050                                         r_cond, TILEGXcc_EZ));
   1051 
   1052       return r_dst;
   1053     }
   1054   }
   1055 
   1056     /* --------- LITERAL --------- */
   1057     /* 32/16/8-bit literals */
   1058   case Iex_Const: {
   1059     Long l;
   1060     HReg r_dst = newVRegI(env);
   1061     IRConst *con = e->Iex.Const.con;
   1062     switch (con->tag) {
   1063     case Ico_U64:
   1064 
   1065       l = (Long) con->Ico.U64;
   1066       break;
   1067     case Ico_U32:
   1068       l = (Long) (Int) con->Ico.U32;
   1069       break;
   1070     case Ico_U16:
   1071       l = (Long) (Int) (Short) con->Ico.U16;
   1072       break;
   1073     case Ico_U8:
   1074       l = (Long) (Int) (Char) con->Ico.U8;
   1075       break;
   1076     default:
   1077       vpanic("iselIntExpr_R.const(tilegx)");
   1078     }
   1079     addInstr(env, TILEGXInstr_LI(r_dst, (ULong) l));
   1080     return r_dst;
   1081   }
   1082 
   1083     /* --------- CCALL --------- */
   1084   case Iex_CCall: {
   1085     HReg r_dst = newVRegI(env);
   1086     vassert(ty == e->Iex.CCall.retty);
   1087 
   1088     /* Marshal args, do the call, clear stack. */
   1089     doHelperCall(env, NULL, e->Iex.CCall.cee, e->Iex.CCall.args,
   1090                  e->Iex.CCall.retty);
   1091 
   1092     /* r0 is the return value. */
   1093     addInstr(env, mk_iMOVds_RR(r_dst, hregTILEGX_R0()));
   1094 
   1095     return r_dst;
   1096   }
   1097 
   1098   default:
   1099     goto irreducible;
   1100     break;
   1101   }        /* end switch(e->tag) */
   1102 
   1103   /* We get here if no pattern matched. */
   1104  irreducible:
   1105   vex_printf("--------------->\n");
   1106   if (e->tag == Iex_RdTmp)
   1107     vex_printf("Iex_RdTmp \n");
   1108   ppIRExpr(e);
   1109 
   1110   vpanic("iselWordExpr_R(tilegx): cannot reduce tree");
   1111 }
   1112 
   1113 /* --------------------- RH --------------------- */
   1114 
   1115 /* Compute an I8/I16/I32/I64 into a RH
   1116    (reg-or-halfword-immediate).  It's important to specify whether the
   1117    immediate is to be regarded as signed or not.  If yes, this will
   1118    never return -32768 as an immediate; this guaranteed that all
   1119    signed immediates that are return can have their sign inverted if
   1120    need be. */
   1121 
   1122 static TILEGXRH *iselWordExpr_RH ( ISelEnv * env, Bool syned, IRExpr * e )
   1123 {
   1124   TILEGXRH *ri = iselWordExpr_RH_wrk(env, syned, e);
   1125   /* sanity checks ... */
   1126   switch (ri->tag) {
   1127   case GXrh_Imm:
   1128     vassert(ri->GXrh.Imm.syned == syned);
   1129     if (syned)
   1130       vassert(ri->GXrh.Imm.imm16 != 0x8000);
   1131     return ri;
   1132   case GXrh_Reg:
   1133     vassert(hregClass(ri->GXrh.Reg.reg) == HRcGPR());
   1134     vassert(hregIsVirtual(ri->GXrh.Reg.reg));
   1135     return ri;
   1136   default:
   1137     vpanic("iselIntExpr_RH: unknown tilegx RH tag");
   1138   }
   1139 }
   1140 
   1141 /* DO NOT CALL THIS DIRECTLY ! */
   1142 static TILEGXRH *iselWordExpr_RH_wrk ( ISelEnv * env, Bool syned, IRExpr * e )
   1143 {
   1144   ULong u;
   1145   Long l;
   1146   IRType ty = typeOfIRExpr(env->type_env, e);
   1147   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
   1148           ((ty == Ity_I64)));
   1149 
   1150   /* special case: immediate */
   1151   if (e->tag == Iex_Const) {
   1152     IRConst *con = e->Iex.Const.con;
   1153     /* What value are we aiming to generate? */
   1154     switch (con->tag) {
   1155       /* Note: Not sign-extending - we carry 'syned' around */
   1156     case Ico_U64:
   1157       u = con->Ico.U64;
   1158       break;
   1159     case Ico_U32:
   1160       u = 0xFFFFFFFF & con->Ico.U32;
   1161       break;
   1162     case Ico_U16:
   1163       u = 0x0000FFFF & con->Ico.U16;
   1164       break;
   1165     case Ico_U8:
   1166       u = 0x000000FF & con->Ico.U8;
   1167       break;
   1168     default:
   1169       vpanic("iselIntExpr_RH.Iex_Const(tilegx)");
   1170     }
   1171     l = (Long) u;
   1172     /* Now figure out if it's representable. */
   1173     if (!syned && u <= 255) {
   1174       return TILEGXRH_Imm(False /*unsigned */ , toUShort(u & 0xFFFF));
   1175     }
   1176     if (syned && l >= -127 && l <= 127) {
   1177       return TILEGXRH_Imm(True /*signed */ , toUShort(u & 0xFFFF));
   1178     }
   1179     /* no luck; use the Slow Way. */
   1180   }
   1181   /* default case: calculate into a register and return that */
   1182   return TILEGXRH_Reg(iselWordExpr_R(env, e));
   1183 }
   1184 
   1185 /* --------------------- RH6u --------------------- */
   1186 
   1187 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter
   1188    being an immediate in the range 0 .. 63 inclusive.  Used for doing
   1189    shift amounts. */
   1190 
   1191 static TILEGXRH *iselWordExpr_RH6u ( ISelEnv * env, IRExpr * e )
   1192 {
   1193   TILEGXRH *ri;
   1194   ri = iselWordExpr_RH6u_wrk(env, e);
   1195   /* sanity checks ... */
   1196   switch (ri->tag) {
   1197   case GXrh_Imm:
   1198     vassert(ri->GXrh.Imm.imm16 >= 1 && ri->GXrh.Imm.imm16 <= 63);
   1199     vassert(!ri->GXrh.Imm.syned);
   1200     return ri;
   1201   case GXrh_Reg:
   1202     vassert(hregClass(ri->GXrh.Reg.reg) == HRcInt64);
   1203     vassert(hregIsVirtual(ri->GXrh.Reg.reg));
   1204     return ri;
   1205   default:
   1206     vpanic("iselIntExpr_RH6u: unknown tilegx RH tag");
   1207   }
   1208 }
   1209 
   1210 /* DO NOT CALL THIS DIRECTLY ! */
   1211 static TILEGXRH *iselWordExpr_RH6u_wrk ( ISelEnv * env, IRExpr * e )
   1212 {
   1213   IRType ty = typeOfIRExpr(env->type_env, e);
   1214 
   1215   /* special case: immediate */
   1216   if (e->tag == Iex_Const)
   1217   {
   1218     if (ty == Ity_I8)
   1219     {
   1220       if(e->Iex.Const.con->tag == Ico_U8
   1221          && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 63)
   1222         return TILEGXRH_Imm(False /*unsigned */ , e->Iex.Const.con->Ico.U8);
   1223     }
   1224     else if (ty == Ity_I64)
   1225     {
   1226       if(e->Iex.Const.con->tag == Ico_U64
   1227          && e->Iex.Const.con->Ico.U64 >= 1
   1228          && e->Iex.Const.con->Ico.U64 <= 63)
   1229         return TILEGXRH_Imm(False /*unsigned */, e->Iex.Const.con->Ico.U64);
   1230     }
   1231   }
   1232 
   1233   /* default case: calculate into a register and return that */
   1234   return TILEGXRH_Reg(iselWordExpr_R(env, e));
   1235 }
   1236 
   1237 /* --------------------- CONDCODE --------------------- */
   1238 
   1239 /* Generate code to evaluated a bit-typed expression, returning the
   1240    condition code which would correspond when the expression would
   1241    notionally have returned 1. */
   1242 
   1243 static TILEGXCondCode iselCondCode(ISelEnv * env, IRExpr * e)
   1244 {
   1245   TILEGXCondCode cc = iselCondCode_wrk(env,e);
   1246   vassert(cc != TILEGXcc_NV);
   1247   return cc;
   1248 }
   1249 
   1250 /* DO NOT CALL THIS DIRECTLY ! */
   1251 static TILEGXCondCode iselCondCode_wrk ( ISelEnv * env, IRExpr * e )
   1252 {
   1253   vassert(e);
   1254   vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
   1255 
   1256   /* Cmp*(x,y) ? */
   1257   if (e->Iex.Binop.op == Iop_CmpEQ32
   1258       || e->Iex.Binop.op == Iop_CmpNE32
   1259       || e->Iex.Binop.op == Iop_CmpNE64
   1260       || e->Iex.Binop.op == Iop_CmpLT32S
   1261       || e->Iex.Binop.op == Iop_CmpLT32U
   1262       || e->Iex.Binop.op == Iop_CmpLT64U
   1263       || e->Iex.Binop.op == Iop_CmpLE32S
   1264       || e->Iex.Binop.op == Iop_CmpLE64S
   1265       || e->Iex.Binop.op == Iop_CmpLT64S
   1266       || e->Iex.Binop.op == Iop_CmpEQ64
   1267       || e->Iex.Binop.op == Iop_CasCmpEQ32
   1268       || e->Iex.Binop.op == Iop_CasCmpEQ64) {
   1269 
   1270     Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
   1271                   || e->Iex.Binop.op == Iop_CmpLE32S
   1272                   || e->Iex.Binop.op == Iop_CmpLT64S
   1273                   || e->Iex.Binop.op == Iop_CmpLE64S);
   1274     Bool size32;
   1275     HReg dst = newVRegI(env);
   1276     HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
   1277     HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
   1278 
   1279     TILEGXCondCode cc;
   1280 
   1281     switch (e->Iex.Binop.op) {
   1282     case Iop_CmpEQ32:
   1283     case Iop_CasCmpEQ32:
   1284       cc = TILEGXcc_EQ;
   1285       size32 = True;
   1286       break;
   1287     case Iop_CmpNE32:
   1288       cc = TILEGXcc_NE;
   1289       size32 = True;
   1290       break;
   1291     case Iop_CmpNE64:
   1292       cc = TILEGXcc_NE;
   1293       size32 = True;
   1294       break;
   1295     case Iop_CmpLT32S:
   1296       cc = TILEGXcc_LT;
   1297       size32 = True;
   1298       break;
   1299     case Iop_CmpLT32U:
   1300       cc = TILEGXcc_LO;
   1301       size32 = True;
   1302       break;
   1303     case Iop_CmpLT64U:
   1304       cc = TILEGXcc_LO;
   1305       size32 = False;
   1306       break;
   1307     case Iop_CmpLE32S:
   1308       cc = TILEGXcc_LE;
   1309       size32 = True;
   1310       break;
   1311     case Iop_CmpLE64S:
   1312       cc = TILEGXcc_LE;
   1313       size32 = False;
   1314       break;
   1315     case Iop_CmpLT64S:
   1316       cc = TILEGXcc_LT;
   1317       size32 = False;
   1318       break;
   1319     case Iop_CmpEQ64:
   1320     case Iop_CasCmpEQ64:
   1321       cc = TILEGXcc_EQ;
   1322       size32 = False;
   1323       break;
   1324     default:
   1325       vpanic("iselCondCode(tilegx): CmpXX32 or CmpXX64");
   1326       break;
   1327     }
   1328 
   1329     addInstr(env, TILEGXInstr_Cmp(syned, size32, dst, r1, r2, cc));
   1330     /* Store result to guest_COND */
   1331     TILEGXAMode *am_addr = TILEGXAMode_IR(0, TILEGXGuestStatePointer());
   1332 
   1333     addInstr(env, TILEGXInstr_Store(8,
   1334                                     TILEGXAMode_IR(am_addr->GXam.IR.index +
   1335                                                    COND_OFFSET(),
   1336                                                    am_addr->GXam.IR.base),
   1337                                     dst));
   1338     return cc;
   1339   }
   1340 
   1341   if (e->Iex.Binop.op == Iop_Not1) {
   1342     HReg r_dst = newVRegI(env);
   1343     HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
   1344     TILEGXRH *r_srcR = TILEGXRH_Reg(r_srcL);
   1345 
   1346     addInstr(env, TILEGXInstr_LI(r_dst, 0x1));
   1347     addInstr(env, TILEGXInstr_Alu(GXalu_SUB, r_dst, r_dst, r_srcR));
   1348 
   1349    /* Store result to guest_COND */
   1350     TILEGXAMode *am_addr = TILEGXAMode_IR(0, TILEGXGuestStatePointer());
   1351 
   1352     addInstr(env, TILEGXInstr_Store(8,
   1353                                     TILEGXAMode_IR(am_addr->GXam.IR.index +
   1354                                                    COND_OFFSET(),
   1355                                                    am_addr->GXam.IR.base),
   1356                                     r_dst));
   1357     return TILEGXcc_NE;
   1358   }
   1359 
   1360   if (e->tag == Iex_RdTmp || e->tag == Iex_Unop) {
   1361     HReg r_dst = iselWordExpr_R_wrk(env, e);
   1362     /* Store result to guest_COND */
   1363     TILEGXAMode *am_addr = TILEGXAMode_IR(0, TILEGXGuestStatePointer());
   1364 
   1365     addInstr(env, TILEGXInstr_Store(8,
   1366                                     TILEGXAMode_IR(am_addr->GXam.IR.index +
   1367                                                    COND_OFFSET(),
   1368                                                    am_addr->GXam.IR.base),
   1369                                     r_dst));
   1370     return TILEGXcc_EQ;
   1371   }
   1372 
   1373   vex_printf("iselCondCode(tilegx): No such tag(%u)\n", e->tag);
   1374   ppIRExpr(e);
   1375   vpanic("iselCondCode(tilegx)");
   1376 
   1377   /* Constant 1:Bit */
   1378   if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True)
   1379     return TILEGXcc_AL;
   1380 
   1381   if (e->tag == Iex_RdTmp)
   1382     return TILEGXcc_EQ;
   1383 
   1384   if (e->tag == Iex_Binop)
   1385     return TILEGXcc_EQ;
   1386 
   1387   if (e->tag == Iex_Unop)
   1388     return TILEGXcc_EQ;
   1389 
   1390   vex_printf("iselCondCode(tilegx): No such tag(%u)\n", e->tag);
   1391   ppIRExpr(e);
   1392   vpanic("iselCondCode(tilegx)");
   1393 }
   1394 
   1395 /*---------------------------------------------------------*/
   1396 /*--- ISEL: Statements                                  ---*/
   1397 /*---------------------------------------------------------*/
   1398 
   1399 static void iselStmt ( ISelEnv * env, IRStmt * stmt )
   1400 {
   1401   if (vex_traceflags & VEX_TRACE_VCODE) {
   1402     vex_printf("\n-- ");
   1403     ppIRStmt(stmt);
   1404     vex_printf("\n");
   1405   }
   1406 
   1407   switch (stmt->tag) {
   1408     /* --------- STORE --------- */
   1409   case Ist_Store: {
   1410     TILEGXAMode *am_addr;
   1411     IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
   1412 
   1413     /*constructs addressing mode from address provided */
   1414     am_addr = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd);
   1415 
   1416     if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
   1417         (tyd == Ity_I64)) {
   1418       HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
   1419       addInstr(env, TILEGXInstr_Store(toUChar(sizeofIRType(tyd)),
   1420                                       am_addr, r_src));
   1421       return;
   1422     }
   1423     break;
   1424   }
   1425 
   1426     /* --------- PUT --------- */
   1427   case Ist_Put: {
   1428     IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
   1429 
   1430     if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
   1431         (ty == Ity_I64)) {
   1432       HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
   1433       TILEGXAMode *am_addr = TILEGXAMode_IR(stmt->Ist.Put.offset,
   1434                                             TILEGXGuestStatePointer());
   1435       addInstr(env, TILEGXInstr_Store(toUChar(sizeofIRType(ty)),
   1436                                       am_addr, r_src));
   1437       return;
   1438     }
   1439     break;
   1440   }
   1441 
   1442     /* --------- TMP --------- */
   1443   case Ist_WrTmp: {
   1444     IRTemp tmp = stmt->Ist.WrTmp.tmp;
   1445     IRType ty = typeOfIRTemp(env->type_env, tmp);
   1446     HReg r_dst = lookupIRTemp(env, tmp);
   1447     HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
   1448     IRType dty = typeOfIRExpr(env->type_env, stmt->Ist.WrTmp.data);
   1449 
   1450     if (ty == Ity_I64 || ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8 ||
   1451         (ty == dty))
   1452     {
   1453       addInstr(env, mk_iMOVds_RR(r_dst, r_src));
   1454       return;
   1455     }
   1456     else if (ty == Ity_I1) {
   1457       switch (dty)
   1458       {
   1459       case Ity_I32:
   1460         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_src, r_src, 0, 31));
   1461         break;
   1462       case Ity_I16:
   1463         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_src, r_src, 0, 15));
   1464         break;
   1465       case Ity_I8:
   1466         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_src, r_src, 0, 7));
   1467         break;
   1468       default:
   1469         vassert(0);
   1470       }
   1471 
   1472       addInstr(env, TILEGXInstr_MovCond(r_dst,
   1473                                         hregTILEGX_R63(),
   1474                                         TILEGXRH_Imm(False, 1),
   1475                                         r_src,
   1476                                         TILEGXcc_EZ));
   1477       return;
   1478     }
   1479     break;
   1480   }
   1481 
   1482     /* --------- Call to DIRTY helper --------- */
   1483   case Ist_Dirty: {
   1484     IRType retty;
   1485     IRDirty *d = stmt->Ist.Dirty.details;
   1486 
   1487     /* Marshal args, do the call, clear stack. */
   1488     doHelperCall(env, d->guard, d->cee, d->args, -1);
   1489 
   1490     /* Now figure out what to do with the returned value, if any. */
   1491     if (d->tmp == IRTemp_INVALID)
   1492       /* No return value.  Nothing to do. */
   1493       return;
   1494 
   1495     retty = typeOfIRTemp(env->type_env, d->tmp);
   1496 
   1497     if (retty == Ity_I8 || retty == Ity_I16 || retty == Ity_I32
   1498         || (retty == Ity_I64)) {
   1499       /* The returned value is in r0.  Park it in the register
   1500          associated with tmp. */
   1501       HReg r_dst = lookupIRTemp(env, d->tmp);
   1502       addInstr(env, mk_iMOVds_RR(r_dst, hregTILEGX_R0()));
   1503       return;
   1504     }
   1505     break;
   1506   }
   1507 
   1508 
   1509     /* --------- ACAS --------- */
   1510   case Ist_CAS:
   1511     {
   1512       UChar  sz;
   1513       IRCAS* cas = stmt->Ist.CAS.details;
   1514       IRType ty  = typeOfIRExpr(env->type_env, cas->dataLo);
   1515 
   1516       TILEGXAMode *r_addr = iselWordExpr_AMode(env, cas->addr, Ity_I64);
   1517       HReg r_new  = iselWordExpr_R(env, cas->dataLo);
   1518       HReg r_old  = lookupIRTemp(env,   cas->oldLo);
   1519       HReg r_exp =  INVALID_HREG;
   1520 
   1521       vassert(cas->expdHi == NULL);
   1522       vassert(cas->dataHi == NULL);
   1523       vassert(r_addr->tag == GXam_IR);
   1524       vassert(r_addr->GXam.IR.index == 0);
   1525 
   1526       switch (ty)
   1527       {
   1528       case Ity_I64: sz = 8; break;
   1529       case Ity_I32: sz = 4; break;
   1530       default: vassert(0);
   1531       }
   1532 
   1533       if (cas->expdLo->tag != Iex_Const)
   1534       {
   1535         r_exp = iselWordExpr_R(env, cas->expdLo);
   1536         addInstr(env, TILEGXInstr_Acas(GXacas_CMPEXCH, r_old,
   1537                                        r_addr->GXam.IR.base, r_exp,
   1538                                        r_new, sz));
   1539       }
   1540       else
   1541       {
   1542         if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 0) ||
   1543            (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 0))
   1544         {
   1545           addInstr(env, TILEGXInstr_Acas(GXacas_EXCH, r_old,
   1546                                          r_addr->GXam.IR.base,
   1547                                          r_exp, r_new, sz));
   1548         }
   1549         else if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 2) ||
   1550                 (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 2))
   1551         {
   1552           addInstr(env, TILEGXInstr_Acas(GXacas_FetchAnd, r_old,
   1553                                          r_addr->GXam.IR.base, r_exp,
   1554                                          r_new, sz));
   1555         }
   1556         else if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 3) ||
   1557                 (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 3))
   1558         {
   1559           addInstr(env, TILEGXInstr_Acas(GXacas_FetchAdd, r_old,
   1560                                          r_addr->GXam.IR.base,
   1561                                          r_exp, r_new, sz));
   1562         }
   1563         else if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 4) ||
   1564                 (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 4))
   1565         {
   1566           addInstr(env, TILEGXInstr_Acas(GXacas_FetchOr, r_old,
   1567                                          r_addr->GXam.IR.base, r_exp,
   1568                                          r_new, sz));
   1569         }
   1570         else if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 5) ||
   1571                 (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 5))
   1572         {
   1573           addInstr(env, TILEGXInstr_Acas(GXacas_FetchAddgez, r_old,
   1574                                          r_addr->GXam.IR.base, r_exp,
   1575                                          r_new, sz));
   1576         }
   1577         else
   1578         {
   1579           vassert(0);
   1580         }
   1581       }
   1582       return;
   1583     }
   1584 
   1585     /* --------- INSTR MARK --------- */
   1586     /* Doesn't generate any executable code ... */
   1587   case Ist_IMark:
   1588     return;
   1589 
   1590     /* --------- ABI HINT --------- */
   1591     /* These have no meaning (denotation in the IR) and so we ignore
   1592        them ... if any actually made it this far. */
   1593   case Ist_AbiHint:
   1594     return;
   1595 
   1596     /* --------- NO-OP --------- */
   1597     /* Fairly self-explanatory, wouldn't you say? */
   1598   case Ist_NoOp:
   1599     return;
   1600 
   1601     /* --------- EXIT --------- */
   1602   case Ist_Exit: {
   1603 
   1604     TILEGXCondCode cc   = iselCondCode(env, stmt->Ist.Exit.guard);
   1605     TILEGXAMode*   amPC = TILEGXAMode_IR(stmt->Ist.Exit.offsIP,
   1606                                          TILEGXGuestStatePointer());
   1607 
   1608     /* Case: boring transfer to known address */
   1609     if (stmt->Ist.Exit.jk == Ijk_Boring
   1610         || stmt->Ist.Exit.jk == Ijk_Call
   1611         /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
   1612       if (env->chainingAllowed) {
   1613         /* .. almost always true .. */
   1614         /* Skip the event check at the dst if this is a forwards
   1615            edge. */
   1616         Bool toFastEP  =
   1617           ((Addr64)stmt->Ist.Exit.dst->Ico.U64) > ((Addr64)env->max_ga);
   1618 
   1619         if (0) vex_printf("%s", toFastEP ? "Y" : ",");
   1620         addInstr(env, TILEGXInstr_XDirect(
   1621                    (Addr64)stmt->Ist.Exit.dst->Ico.U64,
   1622                    amPC, cc, toFastEP));
   1623       } else {
   1624         /* .. very occasionally .. */
   1625         /* We can't use chaining, so ask for an assisted transfer,
   1626            as that's the only alternative that is allowable. */
   1627         HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
   1628         addInstr(env, TILEGXInstr_XAssisted(r, amPC, cc, Ijk_Boring));
   1629       }
   1630       return;
   1631     }
   1632 
   1633     /* Case: assisted transfer to arbitrary address */
   1634     switch (stmt->Ist.Exit.jk) {
   1635       /* Keep this list in sync with that in iselNext below */
   1636     case Ijk_ClientReq:
   1637     case Ijk_EmFail:
   1638     case Ijk_EmWarn:
   1639     case Ijk_NoDecode:
   1640     case Ijk_NoRedir:
   1641     case Ijk_SigBUS:
   1642     case Ijk_Yield:
   1643     case Ijk_SigTRAP:
   1644     case Ijk_SigFPE_IntDiv:
   1645     case Ijk_SigFPE_IntOvf:
   1646     case Ijk_Sys_syscall:
   1647     case Ijk_InvalICache:
   1648     case Ijk_Ret:
   1649       {
   1650         HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
   1651         addInstr(env, TILEGXInstr_XAssisted(r, amPC, cc,
   1652                                             stmt->Ist.Exit.jk));
   1653         return;
   1654       }
   1655     default:
   1656       break;
   1657     }
   1658 
   1659     /* Do we ever expect to see any other kind? */
   1660     goto stmt_fail;
   1661   }
   1662 
   1663   default:
   1664     break;
   1665   }
   1666 
   1667  stmt_fail:
   1668   vex_printf("stmt_fail tag: 0x%x\n", stmt->tag);
   1669   ppIRStmt(stmt);
   1670   vpanic("iselStmt:\n");
   1671 }
   1672 
   1673 /*---------------------------------------------------------*/
   1674 /*--- ISEL: Basic block terminators (Nexts)             ---*/
   1675 /*---------------------------------------------------------*/
   1676 
   1677 static void iselNext ( ISelEnv * env, IRExpr * next, IRJumpKind jk,
   1678                        Int offsIP )
   1679 {
   1680 
   1681   if (vex_traceflags & VEX_TRACE_VCODE) {
   1682     vex_printf("\n-- PUT(%d) = ", offsIP);
   1683     ppIRExpr(next);
   1684     vex_printf( "; exit-");
   1685     ppIRJumpKind(jk);
   1686     vex_printf( "\n");
   1687   }
   1688 
   1689   /* Case: boring transfer to known address */
   1690   if (next->tag == Iex_Const) {
   1691     IRConst* cdst = next->Iex.Const.con;
   1692     if (jk == Ijk_Boring || jk == Ijk_Call) {
   1693       /* Boring transfer to known address */
   1694       TILEGXAMode* amPC = TILEGXAMode_IR(offsIP, TILEGXGuestStatePointer());
   1695       if (env->chainingAllowed) {
   1696         /* .. almost always true .. */
   1697         /* Skip the event check at the dst if this is a forwards
   1698            edge. */
   1699         Bool toFastEP = ((Addr64)cdst->Ico.U64) > ((Addr64)env->max_ga);
   1700 
   1701         if (0) vex_printf("%s", toFastEP ? "X" : ".");
   1702         addInstr(env, TILEGXInstr_XDirect((Addr64)cdst->Ico.U64,
   1703                                           amPC, TILEGXcc_AL, toFastEP));
   1704       } else {
   1705         /* .. very occasionally .. */
   1706         /* We can't use chaining, so ask for an assisted transfer,
   1707            as that's the only alternative that is allowable. */
   1708         HReg r = iselWordExpr_R(env, next);
   1709         addInstr(env, TILEGXInstr_XAssisted(r, amPC, TILEGXcc_AL,
   1710                                             Ijk_Boring));
   1711       }
   1712       return;
   1713     }
   1714   }
   1715 
   1716   /* Case: call/return (==boring) transfer to any address */
   1717   switch (jk) {
   1718   case Ijk_Boring: case Ijk_Call: {
   1719     HReg       r     = iselWordExpr_R(env, next);
   1720     TILEGXAMode*  amPC = TILEGXAMode_IR(offsIP,
   1721                                         TILEGXGuestStatePointer());
   1722     if (env->chainingAllowed)
   1723       addInstr(env, TILEGXInstr_XIndir(r, amPC, TILEGXcc_AL));
   1724     else
   1725       addInstr(env, TILEGXInstr_XAssisted(r, amPC, TILEGXcc_AL,
   1726                                           Ijk_Boring));
   1727     return;
   1728   }
   1729   default:
   1730     break;
   1731   }
   1732 
   1733   /* Case: assisted transfer to arbitrary address */
   1734   switch (jk) {
   1735     /* Keep this list in sync with that for Ist_Exit above */
   1736   case Ijk_ClientReq:
   1737   case Ijk_EmFail:
   1738   case Ijk_EmWarn:
   1739   case Ijk_NoDecode:
   1740   case Ijk_NoRedir:
   1741   case Ijk_SigBUS:
   1742   case Ijk_SigILL:
   1743   case Ijk_SigTRAP:
   1744   case Ijk_SigFPE_IntDiv:
   1745   case Ijk_SigFPE_IntOvf:
   1746   case Ijk_Sys_syscall:
   1747   case Ijk_InvalICache:
   1748   case Ijk_Ret: {
   1749     HReg  r = iselWordExpr_R(env, next);
   1750     TILEGXAMode* amPC = TILEGXAMode_IR(offsIP, TILEGXGuestStatePointer());
   1751     addInstr(env, TILEGXInstr_XAssisted(r, amPC, TILEGXcc_AL, jk));
   1752     return;
   1753   }
   1754   default:
   1755     break;
   1756   }
   1757 
   1758   vex_printf("\n-- PUT(%d) = ", offsIP);
   1759   ppIRExpr(next );
   1760   vex_printf("; exit-");
   1761   ppIRJumpKind(jk);
   1762   vex_printf("\n");
   1763   vassert(0);  /* are we expecting any other kind? */
   1764 }
   1765 
   1766 /*---------------------------------------------------------*/
   1767 /*--- Insn selector top-level                           ---*/
   1768 /*---------------------------------------------------------*/
   1769 
   1770 /* Translate an entire BB to tilegx code. */
   1771 HInstrArray *iselSB_TILEGX ( const IRSB* bb,
   1772                              VexArch arch_host,
   1773                              const VexArchInfo* archinfo_host,
   1774                              const VexAbiInfo* vbi,
   1775                              Int offs_Host_EvC_Counter,
   1776                              Int offs_Host_EvC_FailAddr,
   1777                              Bool chainingAllowed,
   1778                              Bool addProfInc,
   1779                              Addr max_ga )
   1780 {
   1781   Int i, j;
   1782   HReg hreg;
   1783   ISelEnv *env;
   1784   UInt hwcaps_host = archinfo_host->hwcaps;
   1785   TILEGXAMode *amCounter, *amFailAddr;
   1786 
   1787   /* sanity ... */
   1788   vassert(arch_host == VexArchTILEGX);
   1789 
   1790   /* Make up an initial environment to use. */
   1791   env = LibVEX_Alloc(sizeof(ISelEnv));
   1792   env->vreg_ctr = 0;
   1793   env->mode64 = True;
   1794 
   1795   /* Set up output code array. */
   1796   env->code = newHInstrArray();
   1797 
   1798   /* Copy BB's type env. */
   1799   env->type_env = bb->tyenv;
   1800 
   1801   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
   1802      change as we go along. */
   1803   env->n_vregmap = bb->tyenv->types_used;
   1804   env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
   1805 
   1806   /* and finally ... */
   1807   env->hwcaps = hwcaps_host;
   1808   env->chainingAllowed = chainingAllowed;
   1809   env->hwcaps          = hwcaps_host;
   1810   env->max_ga          = max_ga;
   1811 
   1812   /* For each IR temporary, allocate a suitably-kinded virtual
   1813      register. */
   1814   j = 0;
   1815 
   1816   for (i = 0; i < env->n_vregmap; i++) {
   1817     hreg = INVALID_HREG;
   1818     switch (bb->tyenv->types[i]) {
   1819     case Ity_I1:
   1820     case Ity_I8:
   1821     case Ity_I16:
   1822     case Ity_I32:
   1823       hreg = mkHReg(True, HRcInt64, 0, j++);
   1824       break;
   1825     case Ity_I64:
   1826       hreg = mkHReg(True, HRcInt64, 0, j++);
   1827       break;
   1828     default:
   1829       ppIRType(bb->tyenv->types[i]);
   1830       vpanic("iselBB(tilegx): IRTemp type");
   1831     }
   1832     env->vregmap[i] = hreg;
   1833   }
   1834   env->vreg_ctr = j;
   1835 
   1836   /* The very first instruction must be an event check. */
   1837   amCounter = TILEGXAMode_IR(offs_Host_EvC_Counter,
   1838                              TILEGXGuestStatePointer());
   1839   amFailAddr = TILEGXAMode_IR(offs_Host_EvC_FailAddr,
   1840                               TILEGXGuestStatePointer());
   1841   addInstr(env, TILEGXInstr_EvCheck(amCounter, amFailAddr));
   1842 
   1843   /* Possibly a block counter increment (for profiling).  At this
   1844      point we don't know the address of the counter, so just pretend
   1845      it is zero.  It will have to be patched later, but before this
   1846      translation is used, by a call to LibVEX_patchProfCtr. */
   1847   if (addProfInc) {
   1848     addInstr(env, TILEGXInstr_ProfInc());
   1849   }
   1850 
   1851   /* Ok, finally we can iterate over the statements. */
   1852   for (i = 0; i < bb->stmts_used; i++)
   1853     iselStmt(env, bb->stmts[i]);
   1854 
   1855   iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
   1856 
   1857   /* record the number of vregs we used. */
   1858   env->code->n_vregs = env->vreg_ctr;
   1859   return env->code;
   1860 }
   1861 
   1862 /*---------------------------------------------------------------*/
   1863 /*--- end                                  host_tilegx_isel.c ---*/
   1864 /*---------------------------------------------------------------*/
   1865