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-2013 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=%d, nBBPTRs=%d\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   Int i = u & 0xFFFF;
375   i <<= 16;
376   i >>= 16;
377   return toBool(u == (UInt) i);
378 }
379 
sane_AMode(ISelEnv * env,TILEGXAMode * am)380 static Bool sane_AMode ( ISelEnv * env, TILEGXAMode * am )
381 {
382   if (am->tag == GXam_IR)
383     return toBool(hregClass(am->GXam.IR.base) == HRcGPR() &&
384                   hregIsVirtual(am->GXam.IR.base) &&
385                   uInt_fits_in_16_bits(am->GXam.IR.index));
386 
387   vpanic("sane_AMode: unknown tilegx amode tag");
388 }
389 
iselWordExpr_AMode(ISelEnv * env,IRExpr * e,IRType xferTy)390 static TILEGXAMode *iselWordExpr_AMode ( ISelEnv * env, IRExpr * e,
391                                          IRType xferTy )
392 {
393   TILEGXAMode *am = iselWordExpr_AMode_wrk(env, e, xferTy);
394   vassert(sane_AMode(env, am));
395   return am;
396 }
397 
398 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_AMode_wrk(ISelEnv * env,IRExpr * e,IRType xferTy)399 static TILEGXAMode *iselWordExpr_AMode_wrk ( ISelEnv * env, IRExpr * e,
400                                              IRType xferTy )
401 {
402   IRType ty = typeOfIRExpr(env->type_env, e);
403 
404   vassert(ty == Ity_I64);
405   /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
406   if (e->tag == Iex_Binop
407       && e->Iex.Binop.op == Iop_Add64
408       && e->Iex.Binop.arg2->tag == Iex_Const
409       && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
410       && uInt_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)) {
411 
412     return TILEGXAMode_IR((Long) e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
413                           iselWordExpr_R(env, e->Iex.Binop.arg1));
414   }
415 
416   /* Doesn't match anything in particular.  Generate it into
417      a register and use that. */
418   return TILEGXAMode_IR(0, iselWordExpr_R(env, e));
419 }
420 
421 
422 
423 
424 
425 /*---------------------------------------------------------*/
426 /*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
427 /*---------------------------------------------------------*/
428 
429 /* Select insns for an integer-typed expression, and add them to the
430    code list.  Return a reg holding the result.  This reg will be a
431    virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
432    want to modify it, ask for a new vreg, copy it in there, and modify
433    the copy.  The register allocator will do its best to map both
434    add vregs to the same real register, so the copies will often disappear
435    later in the game.
436 
437    This should handle expressions of 64, 32, 16 and 8-bit type.
438    All results are returned in a  64bit register.
439 */
iselWordExpr_R(ISelEnv * env,IRExpr * e)440 static HReg iselWordExpr_R ( ISelEnv * env, IRExpr * e )
441 {
442   HReg r = iselWordExpr_R_wrk(env, e);
443   /* sanity checks ... */
444 
445   vassert(hregClass(r) == HRcGPR());
446   vassert(hregIsVirtual(r));
447   return r;
448 }
449 
450 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_R_wrk(ISelEnv * env,IRExpr * e)451 static HReg iselWordExpr_R_wrk ( ISelEnv * env, IRExpr * e )
452 {
453   IRType ty = typeOfIRExpr(env->type_env, e);
454   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
455           ty == Ity_I1 || ty == Ity_I64);
456 
457   switch (e->tag) {
458     /* --------- TEMP --------- */
459   case Iex_RdTmp:
460     return lookupIRTemp(env, e->Iex.RdTmp.tmp);
461 
462     /* --------- LOAD --------- */
463   case Iex_Load: {
464     HReg r_dst = newVRegI(env);
465     TILEGXAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
466 
467     if (e->Iex.Load.end != Iend_LE
468         && e->Iex.Load.end != Iend_BE)
469       goto irreducible;
470 
471     addInstr(env, TILEGXInstr_Load(toUChar(sizeofIRType(ty)),
472                                    r_dst, am_addr));
473     return r_dst;
474     break;
475   }
476     /* --------- BINARY OP --------- */
477   case Iex_Binop: {
478     TILEGXAluOp aluOp;
479     TILEGXShftOp shftOp;
480 
481     switch (e->Iex.Binop.op) {
482 
483     case Iop_Add8:
484     case Iop_Add16:
485     case Iop_Add32:
486     case Iop_Add64:
487       aluOp = GXalu_ADD;
488       break;
489 
490     case Iop_Sub8:
491     case Iop_Sub16:
492     case Iop_Sub32:
493     case Iop_Sub64:
494       aluOp = GXalu_SUB;
495       break;
496 
497     case Iop_And8:
498     case Iop_And16:
499     case Iop_And32:
500     case Iop_And64:
501       aluOp = GXalu_AND;
502       break;
503 
504     case Iop_Or8:
505     case Iop_Or16:
506     case Iop_Or32:
507     case Iop_Or64:
508       aluOp = GXalu_OR;
509       break;
510 
511     case Iop_Xor8:
512     case Iop_Xor16:
513     case Iop_Xor32:
514     case Iop_Xor64:
515       aluOp = GXalu_XOR;
516       break;
517 
518     default:
519       aluOp = GXalu_INVALID;
520       break;
521     }
522 
523     /* For commutative ops we assume any literal
524        values are on the second operand. */
525     if (aluOp != GXalu_INVALID) {
526       HReg r_dst = newVRegI(env);
527       HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
528       TILEGXRH *ri_srcR = NULL;
529       /* get right arg into an RH, in the appropriate way */
530       switch (aluOp) {
531       case GXalu_ADD:
532       case GXalu_SUB:
533         ri_srcR = iselWordExpr_RH(env, True /*signed */ ,
534                                   e->Iex.Binop.arg2);
535         break;
536       case GXalu_AND:
537       case GXalu_OR:
538       case GXalu_XOR:
539         ri_srcR = iselWordExpr_RH(env, True /*signed */,
540                                   e->Iex.Binop.arg2);
541         break;
542       default:
543         vpanic("iselWordExpr_R_wrk-aluOp-arg2");
544       }
545       addInstr(env, TILEGXInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
546       return r_dst;
547     }
548 
549     /* a shift? */
550     switch (e->Iex.Binop.op) {
551     case Iop_Shl32:
552     case Iop_Shl64:
553       shftOp = GXshft_SLL;
554       break;
555     case Iop_Shr32:
556     case Iop_Shr64:
557       shftOp = GXshft_SRL;
558       break;
559     case Iop_Sar64:
560       shftOp = GXshft_SRA;
561       break;
562     case Iop_Shl8x8:
563       shftOp = GXshft_SLL8x8;
564       break;
565     case Iop_Shr8x8:
566       shftOp = GXshft_SRL8x8;
567       break;
568     default:
569       shftOp = GXshft_INVALID;
570       break;
571     }
572 
573     /* we assume any literal values are on the second operand. */
574     if (shftOp != GXshft_INVALID) {
575       HReg r_dst = newVRegI(env);
576       HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
577       TILEGXRH *ri_srcR = NULL;
578       /* get right arg into an RH, in the appropriate way */
579       switch (shftOp) {
580       case GXshft_SLL:
581       case GXshft_SRL:
582       case GXshft_SRA:
583         //ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
584         //break;
585       case GXshft_SLL8x8:
586       case GXshft_SRL8x8:
587         //if (e->Iex.Binop.arg2->tag == GXrh_Imm)
588         //{
589         // ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
590         //  break;
591         //}
592         ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
593         break;
594       default:
595         vpanic("iselIntExpr_R_wrk-shftOp-arg2");
596       }
597       /* widen the left arg if needed */
598       /*TODO do we need this? */
599       if (ty == Ity_I8 || ty == Ity_I16)
600         goto irreducible;
601       if (ty == Ity_I64) {
602         addInstr(env, TILEGXInstr_Shft(shftOp, False/*64bit shift */,
603                                        r_dst, r_srcL, ri_srcR));
604       } else {
605         addInstr(env, TILEGXInstr_Shft(shftOp, True /*32bit shift */,
606                                        r_dst, r_srcL, ri_srcR));
607       }
608       return r_dst;
609     }
610 
611     /* Cmp*32*(x,y) ? */
612     if (e->Iex.Binop.op == Iop_CasCmpEQ32
613         || e->Iex.Binop.op == Iop_CmpEQ32
614         || e->Iex.Binop.op == Iop_CasCmpNE32
615         || e->Iex.Binop.op == Iop_CmpNE32
616         || e->Iex.Binop.op == Iop_CmpNE64
617         || e->Iex.Binop.op == Iop_CmpLT32S
618         || e->Iex.Binop.op == Iop_CmpLT32U
619         || e->Iex.Binop.op == Iop_CmpLT64U
620         || e->Iex.Binop.op == Iop_CmpLE32S
621         || e->Iex.Binop.op == Iop_CmpLE64S
622         || e->Iex.Binop.op == Iop_CmpLE64U
623         || e->Iex.Binop.op == Iop_CmpLT64S
624         || e->Iex.Binop.op == Iop_CmpEQ64
625         || e->Iex.Binop.op == Iop_CasCmpEQ64
626         || e->Iex.Binop.op == Iop_CasCmpNE64) {
627 
628       Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
629                     || e->Iex.Binop.op == Iop_CmpLE32S
630                     || e->Iex.Binop.op == Iop_CmpLT64S
631                     || e->Iex.Binop.op == Iop_CmpLE64S);
632       Bool size32;
633       HReg dst = newVRegI(env);
634       HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
635       HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
636       TILEGXCondCode cc;
637 
638       switch (e->Iex.Binop.op) {
639       case Iop_CasCmpEQ32:
640       case Iop_CmpEQ32:
641         cc = TILEGXcc_EQ;
642         size32 = True;
643         break;
644       case Iop_CasCmpNE32:
645       case Iop_CmpNE32:
646         cc = TILEGXcc_NE;
647         size32 = True;
648         break;
649       case Iop_CasCmpNE64:
650       case Iop_CmpNE64:
651         cc = TILEGXcc_NE;
652         size32 = True;
653         break;
654       case Iop_CmpLT32S:
655         cc = TILEGXcc_LT;
656         size32 = True;
657         break;
658       case Iop_CmpLT32U:
659         cc = TILEGXcc_LO;
660         size32 = True;
661         break;
662       case Iop_CmpLT64U:
663         cc = TILEGXcc_LT;
664         size32 = False;
665         break;
666       case Iop_CmpLE32S:
667         cc = TILEGXcc_LE;
668         size32 = True;
669         break;
670       case Iop_CmpLE64S:
671         cc = TILEGXcc_LE;
672         size32 = False;
673         break;
674       case Iop_CmpLE64U:
675         cc = TILEGXcc_LE;
676         size32 = False;
677         break;
678       case Iop_CmpLT64S:
679         cc = TILEGXcc_LT;
680         size32 = False;
681         break;
682       case Iop_CasCmpEQ64:
683       case Iop_CmpEQ64:
684         cc = TILEGXcc_EQ;
685         size32 = False;
686         break;
687       default:
688         vpanic
689           ("iselCondCode(tilegx): CmpXX32 or CmpXX64");
690       }
691 
692       addInstr(env, TILEGXInstr_Cmp(syned, size32, dst, r1, r2, cc));
693       return dst;
694 
695       break;
696 
697     }
698 
699     if (e->Iex.Binop.op == Iop_CmpEQ8x8) {
700 
701       Bool syned = False;
702 
703       Bool size32;
704       HReg dst = newVRegI(env);
705       HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
706       TILEGXRH *r2 = iselWordExpr_RH(env, True, e->Iex.Binop.arg2);
707       TILEGXCondCode cc;
708 
709       switch (e->Iex.Binop.op) {
710       case Iop_CmpEQ8x8:
711         cc = TILEGXcc_EQ8x8;
712         size32 = False;
713         break;
714 
715       default:
716         vassert(0);
717       }
718 
719       addInstr(env, TILEGXInstr_CmpI(syned, size32, dst, r1, r2, cc));
720       return dst;
721 
722       break;
723     }
724 
725     if (e->Iex.Binop.op == Iop_Max32U) {
726       /*
727         tmp = argL - argR;
728         tmp &= (1<<31)
729         dst = (tmp) ? (argL) ? (argR)
730       */
731       HReg argL = iselWordExpr_R(env, e->Iex.Binop.arg1);
732       TILEGXRH *argR = iselWordExpr_RH(env, False /*signed */ ,
733                                        e->Iex.Binop.arg2);
734       HReg dst = newVRegI(env);
735       HReg tmp = newVRegI(env);
736       // temp = argL - argR
737       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, tmp, argL, argR));
738       // tmp &= bit31
739       addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, tmp, tmp , 31, 31));
740       // (tmp == 0) ? (argL) : (argR)
741       addInstr(env, TILEGXInstr_MovCond(dst, argL, argR, tmp, TILEGXcc_EZ));
742       return dst;
743     }
744 
745     if (e->Iex.Binop.op == Iop_MullS32 || e->Iex.Binop.op == Iop_MullU32) {
746       Bool syned = (e->Iex.Binop.op == Iop_MullS32);
747       Bool sz32 = (e->Iex.Binop.op == Iop_Mul32);
748       HReg r_dst = newVRegI(env);
749       HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
750       HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
751       addInstr(env, TILEGXInstr_Mul(syned /*Unsigned or Signed */ ,
752                                     True /*widen */ ,
753                                     sz32 /*32bit or 64bit */,
754                                     r_dst, r_srcL, r_srcR));
755       return r_dst;
756     }
757 
758     if (e->Iex.Binop.op == Iop_32HLto64) {
759       HReg tHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
760       HReg tLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
761       HReg tLo_1 = newVRegI(env);
762       HReg tHi_1 = newVRegI(env);
763       HReg r_dst = newVRegI(env);
764       HReg mask = newVRegI(env);
765 
766       addInstr(env, TILEGXInstr_Shft(GXshft_SLL, False, tHi_1, tHi,
767                                      TILEGXRH_Imm(False, 32)));
768 
769       addInstr(env, TILEGXInstr_LI(mask, 0xffffffff));
770       addInstr(env, TILEGXInstr_Alu(GXalu_AND, tLo_1, tLo,
771                                     TILEGXRH_Reg(mask)));
772       addInstr(env, TILEGXInstr_Alu(GXalu_OR, r_dst, tHi_1,
773                                     TILEGXRH_Reg(tLo_1)));
774 
775       return r_dst;
776     }
777 
778     /* Anything reached here !*/
779     goto irreducible;
780   }
781 
782     /* --------- UNARY OP --------- */
783   case Iex_Unop: {
784 
785     IROp op_unop = e->Iex.Unop.op;
786 
787     switch (op_unop) {
788     case Iop_Not1: {
789       HReg r_dst = newVRegI(env);
790       HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
791       TILEGXRH *r_srcR = TILEGXRH_Reg(r_srcL);
792 
793       addInstr(env, TILEGXInstr_LI(r_dst, 0x1));
794       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, r_dst, r_dst, r_srcR));
795       return r_dst;
796     }
797 
798     case Iop_Not8:
799     case Iop_Not16:
800     case Iop_Not32:
801     case Iop_Not64: {
802       /* not x = nor x, x */
803       HReg r_dst = newVRegI(env);
804       HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
805       TILEGXRH *r_srcR = TILEGXRH_Reg(r_srcL);
806 
807       addInstr(env, TILEGXInstr_Alu(GXalu_NOR, r_dst, r_srcL, r_srcR));
808       return r_dst;
809     }
810 
811     case Iop_CmpNEZ8x8: {
812 
813       Bool syned = False;
814       Bool size32;
815       HReg dst = newVRegI(env);
816       HReg r1;
817       TILEGXCondCode cc =  TILEGXcc_NE8x8;
818       size32 = False;
819       r1 = iselWordExpr_R(env, e->Iex.Unop.arg);
820       addInstr(env, TILEGXInstr_CmpI(syned, size32, dst, hregTILEGX_R63(),
821                                      TILEGXRH_Reg(r1), cc));
822 
823       return dst;
824       break;
825     }
826 
827     case Iop_16to8:
828     case Iop_32to8:
829     case Iop_64to8:
830     case Iop_32to16:
831     case Iop_64to16:
832     case Iop_64to32:
833     case Iop_128to64:
834 
835       return iselWordExpr_R(env, e->Iex.Unop.arg);
836 
837     case Iop_1Uto64:
838     case Iop_1Uto32:
839     case Iop_1Uto8: {
840       HReg dst = newVRegI(env);
841       HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
842       addInstr(env, TILEGXInstr_Alu(GXalu_AND, dst, src, TILEGXRH_Imm(False, 1)));
843       return dst;
844     }
845     case Iop_8Uto16:
846     case Iop_8Uto32:
847     case Iop_8Uto64:
848     case Iop_16Uto32:
849     case Iop_16Uto64: {
850 
851       HReg dst     = newVRegI(env);
852       HReg src     = iselWordExpr_R(env, e->Iex.Unop.arg);
853       Bool srcIs16 = toBool( e->Iex.Unop.op==Iop_16Uto32
854                              || e->Iex.Unop.op==Iop_16Uto64 );
855 
856       addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, dst, src,
857                                    0,
858                                    srcIs16 ? 15 : 7));
859 
860       return dst;
861     }
862 
863     case Iop_32to1:
864     case Iop_64to1:
865       {
866         HReg r_dst = newVRegI(env);
867         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
868 
869         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_dst, r_src, 0, 0));
870         return r_dst;
871       }
872     case Iop_1Sto32:
873     case Iop_1Sto64:
874       {
875         HReg r_dst = newVRegI(env);
876         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
877 
878         addInstr(env, TILEGXInstr_Bf(GXbf_EXTS, r_dst, r_src, 0, 0));
879         return r_dst;
880       }
881     case Iop_8Sto16:
882     case Iop_8Sto32:
883     case Iop_8Sto64:
884       {
885         HReg r_dst = newVRegI(env);
886         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
887 
888         addInstr(env, TILEGXInstr_Bf(GXbf_EXTS, r_dst, r_src, 0, 7));
889         return r_dst;
890       }
891     case Iop_16Sto32:
892     case Iop_16Sto64:
893       {
894         HReg r_dst = newVRegI(env);
895         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
896 
897         addInstr(env, TILEGXInstr_Bf(GXbf_EXTS, r_dst, r_src, 0, 15));
898         return r_dst;
899       }
900     case Iop_32Uto64:
901       {
902         HReg r_dst = newVRegI(env);
903         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
904 
905         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_dst, r_src, 0, 31));
906         return r_dst;
907       }
908     case Iop_32Sto64:
909       {
910         HReg r_dst = newVRegI(env);
911         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
912 
913         addInstr(env, TILEGXInstr_Bf(GXbf_EXTS, r_dst, r_src, 0, 31));
914         return r_dst;
915       }
916 
917     case Iop_CmpNEZ8: {
918       HReg r_dst = newVRegI(env);
919       HReg tmp = newVRegI(env);
920       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
921 
922       TILEGXCondCode cc;
923 
924       cc = TILEGXcc_NE;
925       addInstr(env, TILEGXInstr_Alu(GXalu_AND, tmp, r_src,
926                                     TILEGXRH_Imm(False, 0xFF)));
927       addInstr(env, TILEGXInstr_Cmp(False, True, r_dst, tmp,
928                                     hregTILEGX_R63(), cc));
929       return r_dst;
930     }
931 
932     case Iop_CmpNEZ32: {
933       HReg r_dst = newVRegI(env);
934       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
935 
936       TILEGXCondCode cc;
937 
938       cc = TILEGXcc_NE;
939 
940       addInstr(env, TILEGXInstr_Cmp(False, True, r_dst, r_src,
941                                     hregTILEGX_R63(), cc));
942       return r_dst;
943     }
944 
945     case Iop_CmpwNEZ32: {
946       HReg r_dst = newVRegI(env);
947       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
948 
949       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, r_dst, hregTILEGX_R63(),
950                                     TILEGXRH_Reg(r_src)));
951 
952       addInstr(env, TILEGXInstr_Alu(GXalu_OR, r_dst, r_dst,
953                                     TILEGXRH_Reg(r_src)));
954       addInstr(env, TILEGXInstr_Shft(GXshft_SRA, True, r_dst, r_dst,
955                                      TILEGXRH_Imm(False, 31)));
956       return r_dst;
957     }
958 
959     case Iop_Left8:
960     case Iop_Left16:
961     case Iop_Left32:
962     case Iop_Left64: {
963 
964       HReg r_dst = newVRegI(env);
965       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
966       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, r_dst, hregTILEGX_R63(),
967                                     TILEGXRH_Reg(r_src)));
968       addInstr(env, TILEGXInstr_Alu(GXalu_OR, r_dst, r_dst,
969                                     TILEGXRH_Reg(r_src)));
970       return r_dst;
971     }
972 
973     case Iop_Ctz64:
974     case Iop_Clz64: {
975       HReg r_dst = newVRegI(env);
976       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
977       if (op_unop == Iop_Clz64)
978         addInstr(env, TILEGXInstr_Unary(GXun_CLZ, r_dst, r_src));
979       else
980         addInstr(env, TILEGXInstr_Unary(GXun_CTZ, r_dst, r_src));
981       return r_dst;
982     }
983 
984     case Iop_CmpNEZ64: {
985 
986       HReg r_dst = newVRegI(env);
987       HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
988 
989       TILEGXCondCode cc;
990 
991       cc = TILEGXcc_NE;
992 
993       addInstr(env, TILEGXInstr_Cmp(False, False, r_dst, r_src,
994                                     hregTILEGX_R63(), cc));
995       return r_dst;
996     }
997 
998     case Iop_CmpwNEZ64: {
999       HReg tmp1;
1000       HReg tmp2 = newVRegI(env);
1001 
1002       tmp1 = iselWordExpr_R(env, e->Iex.Unop.arg);
1003 
1004       addInstr(env, TILEGXInstr_Alu(GXalu_SUB, tmp2, hregTILEGX_R63(),
1005                                     TILEGXRH_Reg(tmp1)));
1006 
1007       addInstr(env, TILEGXInstr_Alu(GXalu_OR, tmp2, tmp2, TILEGXRH_Reg(tmp1)));
1008       addInstr(env, TILEGXInstr_Shft(GXshft_SRA, False, tmp2, tmp2,
1009                                      TILEGXRH_Imm (False, 63)));
1010       return tmp2;
1011     }
1012 
1013     default:
1014       goto irreducible;
1015       break;
1016     }
1017     break;
1018   }
1019 
1020     /* --------- GET --------- */
1021   case Iex_Get: {
1022     if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32
1023         || ((ty == Ity_I64))) {
1024       HReg r_dst;
1025       TILEGXAMode *am_addr;
1026       r_dst = newVRegI(env);
1027       am_addr = TILEGXAMode_IR(e->Iex.Get.offset,
1028                                TILEGXGuestStatePointer());
1029       addInstr(env, TILEGXInstr_Load(toUChar(sizeofIRType(ty)),
1030                                      r_dst, am_addr));
1031       return r_dst;
1032     }
1033   }
1034 
1035     /* --------- ITE --------- */
1036   case Iex_ITE: {
1037     if ((ty == Ity_I8 || ty == Ity_I16 ||
1038          ty == Ity_I32 || ((ty == Ity_I64))) &&
1039         typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
1040 
1041       HReg r0 = iselWordExpr_R(env, e->Iex.ITE.iffalse);
1042       HReg r1 = iselWordExpr_R(env, e->Iex.ITE.iftrue);
1043       HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
1044       HReg r_dst = newVRegI(env);
1045 
1046       /* r_dst = (r_cond) ? r1 : r0 */
1047 
1048       addInstr(env, TILEGXInstr_MovCond(r_dst, r0, TILEGXRH_Reg(r1),
1049                                         r_cond, TILEGXcc_EZ));
1050 
1051       return r_dst;
1052     }
1053   }
1054 
1055     /* --------- LITERAL --------- */
1056     /* 32/16/8-bit literals */
1057   case Iex_Const: {
1058     Long l;
1059     HReg r_dst = newVRegI(env);
1060     IRConst *con = e->Iex.Const.con;
1061     switch (con->tag) {
1062     case Ico_U64:
1063 
1064       l = (Long) con->Ico.U64;
1065       break;
1066     case Ico_U32:
1067       l = (Long) (Int) con->Ico.U32;
1068       break;
1069     case Ico_U16:
1070       l = (Long) (Int) (Short) con->Ico.U16;
1071       break;
1072     case Ico_U8:
1073       l = (Long) (Int) (Char) con->Ico.U8;
1074       break;
1075     default:
1076       vpanic("iselIntExpr_R.const(tilegx)");
1077     }
1078     addInstr(env, TILEGXInstr_LI(r_dst, (ULong) l));
1079     return r_dst;
1080   }
1081 
1082     /* --------- CCALL --------- */
1083   case Iex_CCall: {
1084     HReg r_dst = newVRegI(env);
1085     vassert(ty == e->Iex.CCall.retty);
1086 
1087     /* Marshal args, do the call, clear stack. */
1088     doHelperCall(env, NULL, e->Iex.CCall.cee, e->Iex.CCall.args,
1089                  e->Iex.CCall.retty);
1090 
1091     /* r0 is the return value. */
1092     addInstr(env, mk_iMOVds_RR(r_dst, hregTILEGX_R0()));
1093 
1094     return r_dst;
1095   }
1096 
1097   default:
1098     goto irreducible;
1099     break;
1100   }        /* end switch(e->tag) */
1101 
1102   /* We get here if no pattern matched. */
1103  irreducible:
1104   vex_printf("--------------->\n");
1105   if (e->tag == Iex_RdTmp)
1106     vex_printf("Iex_RdTmp \n");
1107   ppIRExpr(e);
1108 
1109   vpanic("iselWordExpr_R(tilegx): cannot reduce tree");
1110 }
1111 
1112 /* --------------------- RH --------------------- */
1113 
1114 /* Compute an I8/I16/I32/I64 into a RH
1115    (reg-or-halfword-immediate).  It's important to specify whether the
1116    immediate is to be regarded as signed or not.  If yes, this will
1117    never return -32768 as an immediate; this guaranteed that all
1118    signed immediates that are return can have their sign inverted if
1119    need be. */
1120 
iselWordExpr_RH(ISelEnv * env,Bool syned,IRExpr * e)1121 static TILEGXRH *iselWordExpr_RH ( ISelEnv * env, Bool syned, IRExpr * e )
1122 {
1123   TILEGXRH *ri = iselWordExpr_RH_wrk(env, syned, e);
1124   /* sanity checks ... */
1125   switch (ri->tag) {
1126   case GXrh_Imm:
1127     vassert(ri->GXrh.Imm.syned == syned);
1128     if (syned)
1129       vassert(ri->GXrh.Imm.imm16 != 0x8000);
1130     return ri;
1131   case GXrh_Reg:
1132     vassert(hregClass(ri->GXrh.Reg.reg) == HRcGPR());
1133     vassert(hregIsVirtual(ri->GXrh.Reg.reg));
1134     return ri;
1135   default:
1136     vpanic("iselIntExpr_RH: unknown tilegx RH tag");
1137   }
1138 }
1139 
1140 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH_wrk(ISelEnv * env,Bool syned,IRExpr * e)1141 static TILEGXRH *iselWordExpr_RH_wrk ( ISelEnv * env, Bool syned, IRExpr * e )
1142 {
1143   ULong u;
1144   Long l;
1145   IRType ty = typeOfIRExpr(env->type_env, e);
1146   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
1147           ((ty == Ity_I64)));
1148 
1149   /* special case: immediate */
1150   if (e->tag == Iex_Const) {
1151     IRConst *con = e->Iex.Const.con;
1152     /* What value are we aiming to generate? */
1153     switch (con->tag) {
1154       /* Note: Not sign-extending - we carry 'syned' around */
1155     case Ico_U64:
1156       u = con->Ico.U64;
1157       break;
1158     case Ico_U32:
1159       u = 0xFFFFFFFF & con->Ico.U32;
1160       break;
1161     case Ico_U16:
1162       u = 0x0000FFFF & con->Ico.U16;
1163       break;
1164     case Ico_U8:
1165       u = 0x000000FF & con->Ico.U8;
1166       break;
1167     default:
1168       vpanic("iselIntExpr_RH.Iex_Const(tilegx)");
1169     }
1170     l = (Long) u;
1171     /* Now figure out if it's representable. */
1172     if (!syned && u <= 255) {
1173       return TILEGXRH_Imm(False /*unsigned */ , toUShort(u & 0xFFFF));
1174     }
1175     if (syned && l >= -127 && l <= 127) {
1176       return TILEGXRH_Imm(True /*signed */ , toUShort(u & 0xFFFF));
1177     }
1178     /* no luck; use the Slow Way. */
1179   }
1180   /* default case: calculate into a register and return that */
1181   return TILEGXRH_Reg(iselWordExpr_R(env, e));
1182 }
1183 
1184 /* --------------------- RH6u --------------------- */
1185 
1186 /* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter
1187    being an immediate in the range 0 .. 63 inclusive.  Used for doing
1188    shift amounts. */
1189 
iselWordExpr_RH6u(ISelEnv * env,IRExpr * e)1190 static TILEGXRH *iselWordExpr_RH6u ( ISelEnv * env, IRExpr * e )
1191 {
1192   TILEGXRH *ri;
1193   ri = iselWordExpr_RH6u_wrk(env, e);
1194   /* sanity checks ... */
1195   switch (ri->tag) {
1196   case GXrh_Imm:
1197     vassert(ri->GXrh.Imm.imm16 >= 1 && ri->GXrh.Imm.imm16 <= 63);
1198     vassert(!ri->GXrh.Imm.syned);
1199     return ri;
1200   case GXrh_Reg:
1201     vassert(hregClass(ri->GXrh.Reg.reg) == HRcInt64);
1202     vassert(hregIsVirtual(ri->GXrh.Reg.reg));
1203     return ri;
1204   default:
1205     vpanic("iselIntExpr_RH6u: unknown tilegx RH tag");
1206   }
1207 }
1208 
1209 /* DO NOT CALL THIS DIRECTLY ! */
iselWordExpr_RH6u_wrk(ISelEnv * env,IRExpr * e)1210 static TILEGXRH *iselWordExpr_RH6u_wrk ( ISelEnv * env, IRExpr * e )
1211 {
1212   IRType ty = typeOfIRExpr(env->type_env, e);
1213 
1214   /* special case: immediate */
1215   if (e->tag == Iex_Const)
1216   {
1217     if (ty == Ity_I8)
1218     {
1219       if(e->Iex.Const.con->tag == Ico_U8
1220          && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 63)
1221         return TILEGXRH_Imm(False /*unsigned */ , e->Iex.Const.con->Ico.U8);
1222     }
1223     else if (ty == Ity_I64)
1224     {
1225       if(e->Iex.Const.con->tag == Ico_U64
1226          && e->Iex.Const.con->Ico.U64 >= 1
1227          && e->Iex.Const.con->Ico.U64 <= 63)
1228         return TILEGXRH_Imm(False /*unsigned */, e->Iex.Const.con->Ico.U64);
1229     }
1230   }
1231 
1232   /* default case: calculate into a register and return that */
1233   return TILEGXRH_Reg(iselWordExpr_R(env, e));
1234 }
1235 
1236 /* --------------------- CONDCODE --------------------- */
1237 
1238 /* Generate code to evaluated a bit-typed expression, returning the
1239    condition code which would correspond when the expression would
1240    notionally have returned 1. */
1241 
iselCondCode(ISelEnv * env,IRExpr * e)1242 static TILEGXCondCode iselCondCode(ISelEnv * env, IRExpr * e)
1243 {
1244   TILEGXCondCode cc = iselCondCode_wrk(env,e);
1245   vassert(cc != TILEGXcc_NV);
1246   return cc;
1247 }
1248 
1249 /* DO NOT CALL THIS DIRECTLY ! */
iselCondCode_wrk(ISelEnv * env,IRExpr * e)1250 static TILEGXCondCode iselCondCode_wrk ( ISelEnv * env, IRExpr * e )
1251 {
1252   vassert(e);
1253   vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
1254 
1255   /* Cmp*(x,y) ? */
1256   if (e->Iex.Binop.op == Iop_CmpEQ32
1257       || e->Iex.Binop.op == Iop_CmpNE32
1258       || e->Iex.Binop.op == Iop_CmpNE64
1259       || e->Iex.Binop.op == Iop_CmpLT32S
1260       || e->Iex.Binop.op == Iop_CmpLT32U
1261       || e->Iex.Binop.op == Iop_CmpLT64U
1262       || e->Iex.Binop.op == Iop_CmpLE32S
1263       || e->Iex.Binop.op == Iop_CmpLE64S
1264       || e->Iex.Binop.op == Iop_CmpLT64S
1265       || e->Iex.Binop.op == Iop_CmpEQ64
1266       || e->Iex.Binop.op == Iop_CasCmpEQ32
1267       || e->Iex.Binop.op == Iop_CasCmpEQ64) {
1268 
1269     Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
1270                   || e->Iex.Binop.op == Iop_CmpLE32S
1271                   || e->Iex.Binop.op == Iop_CmpLT64S
1272                   || e->Iex.Binop.op == Iop_CmpLE64S);
1273     Bool size32;
1274     HReg dst = newVRegI(env);
1275     HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
1276     HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
1277 
1278     TILEGXCondCode cc;
1279 
1280     switch (e->Iex.Binop.op) {
1281     case Iop_CmpEQ32:
1282     case Iop_CasCmpEQ32:
1283       cc = TILEGXcc_EQ;
1284       size32 = True;
1285       break;
1286     case Iop_CmpNE32:
1287       cc = TILEGXcc_NE;
1288       size32 = True;
1289       break;
1290     case Iop_CmpNE64:
1291       cc = TILEGXcc_NE;
1292       size32 = True;
1293       break;
1294     case Iop_CmpLT32S:
1295       cc = TILEGXcc_LT;
1296       size32 = True;
1297       break;
1298     case Iop_CmpLT32U:
1299       cc = TILEGXcc_LO;
1300       size32 = True;
1301       break;
1302     case Iop_CmpLT64U:
1303       cc = TILEGXcc_LO;
1304       size32 = False;
1305       break;
1306     case Iop_CmpLE32S:
1307       cc = TILEGXcc_LE;
1308       size32 = True;
1309       break;
1310     case Iop_CmpLE64S:
1311       cc = TILEGXcc_LE;
1312       size32 = False;
1313       break;
1314     case Iop_CmpLT64S:
1315       cc = TILEGXcc_LT;
1316       size32 = False;
1317       break;
1318     case Iop_CmpEQ64:
1319     case Iop_CasCmpEQ64:
1320       cc = TILEGXcc_EQ;
1321       size32 = False;
1322       break;
1323     default:
1324       vpanic("iselCondCode(tilegx): CmpXX32 or CmpXX64");
1325       break;
1326     }
1327 
1328     addInstr(env, TILEGXInstr_Cmp(syned, size32, dst, r1, r2, cc));
1329     /* Store result to guest_COND */
1330     TILEGXAMode *am_addr = TILEGXAMode_IR(0, TILEGXGuestStatePointer());
1331 
1332     addInstr(env, TILEGXInstr_Store(8,
1333                                     TILEGXAMode_IR(am_addr->GXam.IR.index +
1334                                                    COND_OFFSET(),
1335                                                    am_addr->GXam.IR.base),
1336                                     dst));
1337     return cc;
1338   }
1339 
1340   if (e->Iex.Binop.op == Iop_Not1) {
1341     HReg r_dst = newVRegI(env);
1342     HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
1343     TILEGXRH *r_srcR = TILEGXRH_Reg(r_srcL);
1344 
1345     addInstr(env, TILEGXInstr_LI(r_dst, 0x1));
1346     addInstr(env, TILEGXInstr_Alu(GXalu_SUB, r_dst, r_dst, r_srcR));
1347 
1348    /* Store result to guest_COND */
1349     TILEGXAMode *am_addr = TILEGXAMode_IR(0, TILEGXGuestStatePointer());
1350 
1351     addInstr(env, TILEGXInstr_Store(8,
1352                                     TILEGXAMode_IR(am_addr->GXam.IR.index +
1353                                                    COND_OFFSET(),
1354                                                    am_addr->GXam.IR.base),
1355                                     r_dst));
1356     return TILEGXcc_NE;
1357   }
1358 
1359   if (e->tag == Iex_RdTmp || e->tag == Iex_Unop) {
1360     HReg r_dst = iselWordExpr_R_wrk(env, e);
1361     /* Store result to guest_COND */
1362     TILEGXAMode *am_addr = TILEGXAMode_IR(0, TILEGXGuestStatePointer());
1363 
1364     addInstr(env, TILEGXInstr_Store(8,
1365                                     TILEGXAMode_IR(am_addr->GXam.IR.index +
1366                                                    COND_OFFSET(),
1367                                                    am_addr->GXam.IR.base),
1368                                     r_dst));
1369     return TILEGXcc_EQ;
1370   }
1371 
1372   vex_printf("iselCondCode(tilegx): No such tag(%u)\n", e->tag);
1373   ppIRExpr(e);
1374   vpanic("iselCondCode(tilegx)");
1375 
1376   /* Constant 1:Bit */
1377   if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True)
1378     return TILEGXcc_AL;
1379 
1380   if (e->tag == Iex_RdTmp)
1381     return TILEGXcc_EQ;
1382 
1383   if (e->tag == Iex_Binop)
1384     return TILEGXcc_EQ;
1385 
1386   if (e->tag == Iex_Unop)
1387     return TILEGXcc_EQ;
1388 
1389   vex_printf("iselCondCode(tilegx): No such tag(%u)\n", e->tag);
1390   ppIRExpr(e);
1391   vpanic("iselCondCode(tilegx)");
1392 }
1393 
1394 /*---------------------------------------------------------*/
1395 /*--- ISEL: Statements                                  ---*/
1396 /*---------------------------------------------------------*/
1397 
iselStmt(ISelEnv * env,IRStmt * stmt)1398 static void iselStmt ( ISelEnv * env, IRStmt * stmt )
1399 {
1400   if (vex_traceflags & VEX_TRACE_VCODE) {
1401     vex_printf("\n-- ");
1402     ppIRStmt(stmt);
1403     vex_printf("\n");
1404   }
1405 
1406   switch (stmt->tag) {
1407     /* --------- STORE --------- */
1408   case Ist_Store: {
1409     TILEGXAMode *am_addr;
1410     IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
1411 
1412     /*constructs addressing mode from address provided */
1413     am_addr = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd);
1414 
1415     if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
1416         (tyd == Ity_I64)) {
1417       HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
1418       addInstr(env, TILEGXInstr_Store(toUChar(sizeofIRType(tyd)),
1419                                       am_addr, r_src));
1420       return;
1421     }
1422     break;
1423   }
1424 
1425     /* --------- PUT --------- */
1426   case Ist_Put: {
1427     IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
1428 
1429     if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
1430         (ty == Ity_I64)) {
1431       HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
1432       TILEGXAMode *am_addr = TILEGXAMode_IR(stmt->Ist.Put.offset,
1433                                             TILEGXGuestStatePointer());
1434       addInstr(env, TILEGXInstr_Store(toUChar(sizeofIRType(ty)),
1435                                       am_addr, r_src));
1436       return;
1437     }
1438     break;
1439   }
1440 
1441     /* --------- TMP --------- */
1442   case Ist_WrTmp: {
1443     IRTemp tmp = stmt->Ist.WrTmp.tmp;
1444     IRType ty = typeOfIRTemp(env->type_env, tmp);
1445     HReg r_dst = lookupIRTemp(env, tmp);
1446     HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
1447     IRType dty = typeOfIRExpr(env->type_env, stmt->Ist.WrTmp.data);
1448 
1449     if (ty == Ity_I64 || ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8 ||
1450         (ty == dty))
1451     {
1452       addInstr(env, mk_iMOVds_RR(r_dst, r_src));
1453       return;
1454     }
1455     else if (ty == Ity_I1) {
1456       switch (dty)
1457       {
1458       case Ity_I32:
1459         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_src, r_src, 0, 31));
1460         break;
1461       case Ity_I16:
1462         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_src, r_src, 0, 15));
1463         break;
1464       case Ity_I8:
1465         addInstr(env, TILEGXInstr_Bf(GXbf_EXTU, r_src, r_src, 0, 7));
1466         break;
1467       default:
1468         vassert(0);
1469       }
1470 
1471       addInstr(env, TILEGXInstr_MovCond(r_dst,
1472                                         hregTILEGX_R63(),
1473                                         TILEGXRH_Imm(False, 1),
1474                                         r_src,
1475                                         TILEGXcc_EZ));
1476       return;
1477     }
1478     break;
1479   }
1480 
1481     /* --------- Call to DIRTY helper --------- */
1482   case Ist_Dirty: {
1483     IRType retty;
1484     IRDirty *d = stmt->Ist.Dirty.details;
1485 
1486     /* Marshal args, do the call, clear stack. */
1487     doHelperCall(env, d->guard, d->cee, d->args, -1);
1488 
1489     /* Now figure out what to do with the returned value, if any. */
1490     if (d->tmp == IRTemp_INVALID)
1491       /* No return value.  Nothing to do. */
1492       return;
1493 
1494     retty = typeOfIRTemp(env->type_env, d->tmp);
1495 
1496     if (retty == Ity_I8 || retty == Ity_I16 || retty == Ity_I32
1497         || (retty == Ity_I64)) {
1498       /* The returned value is in r0.  Park it in the register
1499          associated with tmp. */
1500       HReg r_dst = lookupIRTemp(env, d->tmp);
1501       addInstr(env, mk_iMOVds_RR(r_dst, hregTILEGX_R0()));
1502       return;
1503     }
1504     break;
1505   }
1506 
1507 
1508     /* --------- ACAS --------- */
1509   case Ist_CAS:
1510     {
1511       UChar  sz;
1512       IRCAS* cas = stmt->Ist.CAS.details;
1513       IRType ty  = typeOfIRExpr(env->type_env, cas->dataLo);
1514 
1515       TILEGXAMode *r_addr = iselWordExpr_AMode(env, cas->addr, Ity_I64);
1516       HReg r_new  = iselWordExpr_R(env, cas->dataLo);
1517       HReg r_old  = lookupIRTemp(env,   cas->oldLo);
1518       HReg r_exp =  INVALID_HREG;
1519 
1520       vassert(cas->expdHi == NULL);
1521       vassert(cas->dataHi == NULL);
1522       vassert(r_addr->tag == GXam_IR);
1523       vassert(r_addr->GXam.IR.index == 0);
1524 
1525       switch (ty)
1526       {
1527       case Ity_I64: sz = 8; break;
1528       case Ity_I32: sz = 4; break;
1529       default: vassert(0);
1530       }
1531 
1532       if (cas->expdLo->tag != Iex_Const)
1533       {
1534         r_exp = iselWordExpr_R(env, cas->expdLo);
1535         addInstr(env, TILEGXInstr_Acas(GXacas_CMPEXCH, r_old,
1536                                        r_addr->GXam.IR.base, r_exp,
1537                                        r_new, sz));
1538       }
1539       else
1540       {
1541         if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 0) ||
1542            (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 0))
1543         {
1544           addInstr(env, TILEGXInstr_Acas(GXacas_EXCH, r_old,
1545                                          r_addr->GXam.IR.base,
1546                                          r_exp, r_new, sz));
1547         }
1548         else if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 2) ||
1549                 (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 2))
1550         {
1551           addInstr(env, TILEGXInstr_Acas(GXacas_FetchAnd, r_old,
1552                                          r_addr->GXam.IR.base, r_exp,
1553                                          r_new, sz));
1554         }
1555         else if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 3) ||
1556                 (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 3))
1557         {
1558           addInstr(env, TILEGXInstr_Acas(GXacas_FetchAdd, r_old,
1559                                          r_addr->GXam.IR.base,
1560                                          r_exp, r_new, sz));
1561         }
1562         else if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 4) ||
1563                 (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 4))
1564         {
1565           addInstr(env, TILEGXInstr_Acas(GXacas_FetchOr, r_old,
1566                                          r_addr->GXam.IR.base, r_exp,
1567                                          r_new, sz));
1568         }
1569         else if((sz == 8 && cas->expdLo->Iex.Const.con->Ico.U64 == 5) ||
1570                 (sz == 4 && cas->expdLo->Iex.Const.con->Ico.U32 == 5))
1571         {
1572           addInstr(env, TILEGXInstr_Acas(GXacas_FetchAddgez, r_old,
1573                                          r_addr->GXam.IR.base, r_exp,
1574                                          r_new, sz));
1575         }
1576         else
1577         {
1578           vassert(0);
1579         }
1580       }
1581       return;
1582     }
1583 
1584     /* --------- INSTR MARK --------- */
1585     /* Doesn't generate any executable code ... */
1586   case Ist_IMark:
1587     return;
1588 
1589     /* --------- ABI HINT --------- */
1590     /* These have no meaning (denotation in the IR) and so we ignore
1591        them ... if any actually made it this far. */
1592   case Ist_AbiHint:
1593     return;
1594 
1595     /* --------- NO-OP --------- */
1596     /* Fairly self-explanatory, wouldn't you say? */
1597   case Ist_NoOp:
1598     return;
1599 
1600     /* --------- EXIT --------- */
1601   case Ist_Exit: {
1602 
1603     TILEGXCondCode cc   = iselCondCode(env, stmt->Ist.Exit.guard);
1604     TILEGXAMode*   amPC = TILEGXAMode_IR(stmt->Ist.Exit.offsIP,
1605                                          TILEGXGuestStatePointer());
1606 
1607     /* Case: boring transfer to known address */
1608     if (stmt->Ist.Exit.jk == Ijk_Boring
1609         || stmt->Ist.Exit.jk == Ijk_Call
1610         /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
1611       if (env->chainingAllowed) {
1612         /* .. almost always true .. */
1613         /* Skip the event check at the dst if this is a forwards
1614            edge. */
1615         Bool toFastEP  =
1616           ((Addr64)stmt->Ist.Exit.dst->Ico.U64) > ((Addr64)env->max_ga);
1617 
1618         if (0) vex_printf("%s", toFastEP ? "Y" : ",");
1619         addInstr(env, TILEGXInstr_XDirect(
1620                    (Addr64)stmt->Ist.Exit.dst->Ico.U64,
1621                    amPC, cc, toFastEP));
1622       } else {
1623         /* .. very occasionally .. */
1624         /* We can't use chaining, so ask for an assisted transfer,
1625            as that's the only alternative that is allowable. */
1626         HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
1627         addInstr(env, TILEGXInstr_XAssisted(r, amPC, cc, Ijk_Boring));
1628       }
1629       return;
1630     }
1631 
1632     /* Case: assisted transfer to arbitrary address */
1633     switch (stmt->Ist.Exit.jk) {
1634       /* Keep this list in sync with that in iselNext below */
1635     case Ijk_ClientReq:
1636     case Ijk_EmFail:
1637     case Ijk_EmWarn:
1638     case Ijk_NoDecode:
1639     case Ijk_NoRedir:
1640     case Ijk_SigBUS:
1641     case Ijk_Yield:
1642     case Ijk_SigTRAP:
1643     case Ijk_SigFPE_IntDiv:
1644     case Ijk_SigFPE_IntOvf:
1645     case Ijk_Sys_syscall:
1646     case Ijk_InvalICache:
1647     case Ijk_Ret:
1648       {
1649         HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
1650         addInstr(env, TILEGXInstr_XAssisted(r, amPC, cc,
1651                                             stmt->Ist.Exit.jk));
1652         return;
1653       }
1654     default:
1655       break;
1656     }
1657 
1658     /* Do we ever expect to see any other kind? */
1659     goto stmt_fail;
1660   }
1661 
1662   default:
1663     break;
1664   }
1665 
1666  stmt_fail:
1667   vex_printf("stmt_fail tag: 0x%x\n", stmt->tag);
1668   ppIRStmt(stmt);
1669   vpanic("iselStmt:\n");
1670 }
1671 
1672 /*---------------------------------------------------------*/
1673 /*--- ISEL: Basic block terminators (Nexts)             ---*/
1674 /*---------------------------------------------------------*/
1675 
iselNext(ISelEnv * env,IRExpr * next,IRJumpKind jk,Int offsIP)1676 static void iselNext ( ISelEnv * env, IRExpr * next, IRJumpKind jk,
1677                        Int offsIP )
1678 {
1679 
1680   if (vex_traceflags & VEX_TRACE_VCODE) {
1681     vex_printf("\n-- PUT(%d) = ", offsIP);
1682     ppIRExpr(next);
1683     vex_printf( "; exit-");
1684     ppIRJumpKind(jk);
1685     vex_printf( "\n");
1686   }
1687 
1688   /* Case: boring transfer to known address */
1689   if (next->tag == Iex_Const) {
1690     IRConst* cdst = next->Iex.Const.con;
1691     if (jk == Ijk_Boring || jk == Ijk_Call) {
1692       /* Boring transfer to known address */
1693       TILEGXAMode* amPC = TILEGXAMode_IR(offsIP, TILEGXGuestStatePointer());
1694       if (env->chainingAllowed) {
1695         /* .. almost always true .. */
1696         /* Skip the event check at the dst if this is a forwards
1697            edge. */
1698         Bool toFastEP = ((Addr64)cdst->Ico.U64) > ((Addr64)env->max_ga);
1699 
1700         if (0) vex_printf("%s", toFastEP ? "X" : ".");
1701         addInstr(env, TILEGXInstr_XDirect((Addr64)cdst->Ico.U64,
1702                                           amPC, TILEGXcc_AL, toFastEP));
1703       } else {
1704         /* .. very occasionally .. */
1705         /* We can't use chaining, so ask for an assisted transfer,
1706            as that's the only alternative that is allowable. */
1707         HReg r = iselWordExpr_R(env, next);
1708         addInstr(env, TILEGXInstr_XAssisted(r, amPC, TILEGXcc_AL,
1709                                             Ijk_Boring));
1710       }
1711       return;
1712     }
1713   }
1714 
1715   /* Case: call/return (==boring) transfer to any address */
1716   switch (jk) {
1717   case Ijk_Boring: case Ijk_Call: {
1718     HReg       r     = iselWordExpr_R(env, next);
1719     TILEGXAMode*  amPC = TILEGXAMode_IR(offsIP,
1720                                         TILEGXGuestStatePointer());
1721     if (env->chainingAllowed)
1722       addInstr(env, TILEGXInstr_XIndir(r, amPC, TILEGXcc_AL));
1723     else
1724       addInstr(env, TILEGXInstr_XAssisted(r, amPC, TILEGXcc_AL,
1725                                           Ijk_Boring));
1726     return;
1727   }
1728   default:
1729     break;
1730   }
1731 
1732   /* Case: assisted transfer to arbitrary address */
1733   switch (jk) {
1734     /* Keep this list in sync with that for Ist_Exit above */
1735   case Ijk_ClientReq:
1736   case Ijk_EmFail:
1737   case Ijk_EmWarn:
1738   case Ijk_NoDecode:
1739   case Ijk_NoRedir:
1740   case Ijk_SigBUS:
1741   case Ijk_SigILL:
1742   case Ijk_SigTRAP:
1743   case Ijk_SigFPE_IntDiv:
1744   case Ijk_SigFPE_IntOvf:
1745   case Ijk_Sys_syscall:
1746   case Ijk_InvalICache:
1747   case Ijk_Ret: {
1748     HReg  r = iselWordExpr_R(env, next);
1749     TILEGXAMode* amPC = TILEGXAMode_IR(offsIP, TILEGXGuestStatePointer());
1750     addInstr(env, TILEGXInstr_XAssisted(r, amPC, TILEGXcc_AL, jk));
1751     return;
1752   }
1753   default:
1754     break;
1755   }
1756 
1757   vex_printf("\n-- PUT(%d) = ", offsIP);
1758   ppIRExpr(next );
1759   vex_printf("; exit-");
1760   ppIRJumpKind(jk);
1761   vex_printf("\n");
1762   vassert(0);  /* are we expecting any other kind? */
1763 }
1764 
1765 /*---------------------------------------------------------*/
1766 /*--- Insn selector top-level                           ---*/
1767 /*---------------------------------------------------------*/
1768 
1769 /* 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)1770 HInstrArray *iselSB_TILEGX ( const IRSB* bb,
1771                              VexArch arch_host,
1772                              const VexArchInfo* archinfo_host,
1773                              const VexAbiInfo* vbi,
1774                              Int offs_Host_EvC_Counter,
1775                              Int offs_Host_EvC_FailAddr,
1776                              Bool chainingAllowed,
1777                              Bool addProfInc,
1778                              Addr max_ga )
1779 {
1780   Int i, j;
1781   HReg hreg;
1782   ISelEnv *env;
1783   UInt hwcaps_host = archinfo_host->hwcaps;
1784   TILEGXAMode *amCounter, *amFailAddr;
1785 
1786   /* sanity ... */
1787   vassert(arch_host == VexArchTILEGX);
1788 
1789   /* Make up an initial environment to use. */
1790   env = LibVEX_Alloc(sizeof(ISelEnv));
1791   env->vreg_ctr = 0;
1792   env->mode64 = True;
1793 
1794   /* Set up output code array. */
1795   env->code = newHInstrArray();
1796 
1797   /* Copy BB's type env. */
1798   env->type_env = bb->tyenv;
1799 
1800   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
1801      change as we go along. */
1802   env->n_vregmap = bb->tyenv->types_used;
1803   env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
1804 
1805   /* and finally ... */
1806   env->hwcaps = hwcaps_host;
1807   env->chainingAllowed = chainingAllowed;
1808   env->hwcaps          = hwcaps_host;
1809   env->max_ga          = max_ga;
1810 
1811   /* For each IR temporary, allocate a suitably-kinded virtual
1812      register. */
1813   j = 0;
1814 
1815   for (i = 0; i < env->n_vregmap; i++) {
1816     hreg = INVALID_HREG;
1817     switch (bb->tyenv->types[i]) {
1818     case Ity_I1:
1819     case Ity_I8:
1820     case Ity_I16:
1821     case Ity_I32:
1822       hreg = mkHReg(True, HRcInt64, 0, j++);
1823       break;
1824     case Ity_I64:
1825       hreg = mkHReg(True, HRcInt64, 0, j++);
1826       break;
1827     default:
1828       ppIRType(bb->tyenv->types[i]);
1829       vpanic("iselBB(tilegx): IRTemp type");
1830     }
1831     env->vregmap[i] = hreg;
1832   }
1833   env->vreg_ctr = j;
1834 
1835   /* The very first instruction must be an event check. */
1836   amCounter = TILEGXAMode_IR(offs_Host_EvC_Counter,
1837                              TILEGXGuestStatePointer());
1838   amFailAddr = TILEGXAMode_IR(offs_Host_EvC_FailAddr,
1839                               TILEGXGuestStatePointer());
1840   addInstr(env, TILEGXInstr_EvCheck(amCounter, amFailAddr));
1841 
1842   /* Possibly a block counter increment (for profiling).  At this
1843      point we don't know the address of the counter, so just pretend
1844      it is zero.  It will have to be patched later, but before this
1845      translation is used, by a call to LibVEX_patchProfCtr. */
1846   if (addProfInc) {
1847     addInstr(env, TILEGXInstr_ProfInc());
1848   }
1849 
1850   /* Ok, finally we can iterate over the statements. */
1851   for (i = 0; i < bb->stmts_used; i++)
1852     iselStmt(env, bb->stmts[i]);
1853 
1854   iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
1855 
1856   /* record the number of vregs we used. */
1857   env->code->n_vregs = env->vreg_ctr;
1858   return env->code;
1859 }
1860 
1861 /*---------------------------------------------------------------*/
1862 /*--- end                                  host_tilegx_isel.c ---*/
1863 /*---------------------------------------------------------------*/
1864