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 
lookupIRTemp(ISelEnv * env,IRTemp tmp)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 
addInstr(ISelEnv * env,TILEGXInstr * instr)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 
newVRegI(ISelEnv * env)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. */
mk_iMOVds_RR(HReg r_dst,HReg r_src)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 */
mightRequireFixedRegs(IRExpr * e)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 
doHelperCall(ISelEnv * env,IRExpr * guard,IRCallee * cee,IRExpr ** args,IRType retTy)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 
uInt_fits_in_16_bits(UInt u)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 
sane_AMode(ISelEnv * env,TILEGXAMode * am)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 
iselWordExpr_AMode(ISelEnv * env,IRExpr * e,IRType xferTy)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 ! */
iselWordExpr_AMode_wrk(ISelEnv * env,IRExpr * e,IRType xferTy)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 */
iselWordExpr_R(ISelEnv * env,IRExpr * e)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 ! */
iselWordExpr_R_wrk(ISelEnv * env,IRExpr * e)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 
iselWordExpr_RH(ISelEnv * env,Bool syned,IRExpr * e)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 ! */
iselWordExpr_RH_wrk(ISelEnv * env,Bool syned,IRExpr * e)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 
iselWordExpr_RH6u(ISelEnv * env,IRExpr * e)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 ! */
iselWordExpr_RH6u_wrk(ISelEnv * env,IRExpr * e)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 
iselCondCode(ISelEnv * env,IRExpr * e)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 ! */
iselCondCode_wrk(ISelEnv * env,IRExpr * e)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 
iselStmt(ISelEnv * env,IRStmt * stmt)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 
iselNext(ISelEnv * env,IRExpr * next,IRJumpKind jk,Int offsIP)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. */
iselSB_TILEGX(const IRSB * bb,VexArch arch_host,const VexArchInfo * archinfo_host,const VexAbiInfo * vbi,Int offs_Host_EvC_Counter,Int offs_Host_EvC_FailAddr,Bool chainingAllowed,Bool addProfInc,Addr max_ga)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