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