278
278
return toBool(x == y1);
281
//.. /* Is this a 32-bit zero expression? */
283
//.. static Bool isZero32 ( IRExpr* e )
285
//.. return e->tag == Iex_Const
286
//.. && e->Iex.Const.con->tag == Ico_U32
287
//.. && e->Iex.Const.con->Ico.U32 == 0;
281
/* Is this a 64-bit zero expression? */
283
static Bool isZeroU64 ( IRExpr* e )
285
return e->tag == Iex_Const
286
&& e->Iex.Const.con->tag == Ico_U64
287
&& e->Iex.Const.con->Ico.U64 == 0ULL;
290
static Bool isZeroU32 ( IRExpr* e )
292
return e->tag == Iex_Const
293
&& e->Iex.Const.con->tag == Ico_U32
294
&& e->Iex.Const.con->Ico.U32 == 0;
290
297
/* Make a int reg-reg move. */
368
/* Used only in doHelperCall. See big comment in doHelperCall re
369
handling of register-parameter args. This function figures out
370
whether evaluation of an expression might require use of a fixed
371
register. If in doubt return True (safe but suboptimal).
374
Bool mightRequireFixedRegs ( IRExpr* e )
375
/* Used only in doHelperCall. If possible, produce a single
376
instruction which computes 'e' into 'dst'. If not possible, return
379
static AMD64Instr* iselIntExpr_single_instruction ( ISelEnv* env,
377
case Iex_Tmp: case Iex_Const: case Iex_Get:
383
vassert(typeOfIRExpr(env->type_env, e) == Ity_I64);
385
if (e->tag == Iex_Const) {
386
vassert(e->Iex.Const.con->tag == Ico_U64);
387
if (fitsIn32Bits(e->Iex.Const.con->Ico.U64)) {
388
return AMD64Instr_Alu64R(
390
AMD64RMI_Imm(toUInt(e->Iex.Const.con->Ico.U64)),
394
return AMD64Instr_Imm64(e->Iex.Const.con->Ico.U64, dst);
398
if (e->tag == Iex_RdTmp) {
399
HReg src = lookupIRTemp(env, e->Iex.RdTmp.tmp);
400
return mk_iMOVsd_RR(src, dst);
403
if (e->tag == Iex_Get) {
404
vassert(e->Iex.Get.ty == Ity_I64);
405
return AMD64Instr_Alu64R(
408
AMD64AMode_IR(e->Iex.Get.offset,
413
if (e->tag == Iex_Unop
414
&& e->Iex.Unop.op == Iop_32Uto64
415
&& e->Iex.Unop.arg->tag == Iex_RdTmp) {
416
HReg src = lookupIRTemp(env, e->Iex.Unop.arg->Iex.RdTmp.tmp);
417
return AMD64Instr_MovZLQ(src, dst);
420
if (0) { ppIRExpr(e); vex_printf("\n"); }
477
519
/* unconditional */
479
521
/* Not manifestly unconditional -- be conservative. */
485
for (i = 0; i < n_args; i++) {
486
if (mightRequireFixedRegs(args[i])) {
493
/* At this point the scheme to use has been established. Generate
494
code to get the arg values into the argument rregs. */
501
addInstr(env, mk_iMOVsd_RR( hregAMD64_RBP(), argregs[argreg]));
505
for (i = 0; i < n_args; i++) {
507
vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
508
addInstr(env, AMD64Instr_Alu64R(
510
iselIntExpr_RMI(env, args[i]),
517
/* Fast scheme only applies for unconditional calls. Hence: */
522
/* SLOW SCHEME; move via temporaries */
526
/* This is pretty stupid; better to move directly to rdi
527
after the rest of the args are done. */
528
tmpregs[argreg] = newVRegI(env);
529
addInstr(env, mk_iMOVsd_RR( hregAMD64_RBP(), tmpregs[argreg]));
533
for (i = 0; i < n_args; i++) {
535
vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
536
tmpregs[argreg] = iselIntExpr_R(env, args[i]);
540
/* Now we can compute the condition. We can't do it earlier
541
because the argument computations could trash the condition
542
codes. Be a bit clever to handle the common case where the
546
if (guard->tag == Iex_Const
547
&& guard->Iex.Const.con->tag == Ico_U1
548
&& guard->Iex.Const.con->Ico.U1 == True) {
549
/* unconditional -- do nothing */
551
cc = iselCondCode( env, guard );
555
/* Move the args to their final destinations. */
556
for (i = 0; i < argreg; i++) {
557
/* None of these insns, including any spill code that might
558
be generated, may alter the condition codes. */
559
addInstr( env, mk_iMOVsd_RR( tmpregs[i], argregs[i] ) );
526
/* Ok, let's try for the fast scheme. If it doesn't pan out, we'll
527
use the slow scheme. Because this is tentative, we can't call
528
addInstr (that is, commit to) any instructions until we're
529
handled all the arguments. So park the resulting instructions
530
in a buffer and emit that if we're successful. */
535
fastinstrs[argreg] = mk_iMOVsd_RR( hregAMD64_RBP(), argregs[argreg]);
539
for (i = 0; i < n_args; i++) {
541
vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
543
= iselIntExpr_single_instruction( env, argregs[argreg], args[i] );
544
if (fastinstrs[argreg] == NULL)
549
/* Looks like we're in luck. Emit the accumulated instructions and
550
move on to doing the call itself. */
551
vassert(argreg <= 6);
552
for (i = 0; i < argreg; i++)
553
addInstr(env, fastinstrs[i]);
555
/* Fast scheme only applies for unconditional calls. Hence: */
561
/* SLOW SCHEME; move via temporaries */
564
if (n_args > 0) {for (i = 0; args[i]; i++) {
565
ppIRExpr(args[i]); vex_printf(" "); }
571
/* This is pretty stupid; better to move directly to rdi
572
after the rest of the args are done. */
573
tmpregs[argreg] = newVRegI(env);
574
addInstr(env, mk_iMOVsd_RR( hregAMD64_RBP(), tmpregs[argreg]));
578
for (i = 0; i < n_args; i++) {
580
vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
581
tmpregs[argreg] = iselIntExpr_R(env, args[i]);
585
/* Now we can compute the condition. We can't do it earlier
586
because the argument computations could trash the condition
587
codes. Be a bit clever to handle the common case where the
591
if (guard->tag == Iex_Const
592
&& guard->Iex.Const.con->tag == Ico_U1
593
&& guard->Iex.Const.con->Ico.U1 == True) {
594
/* unconditional -- do nothing */
596
cc = iselCondCode( env, guard );
600
/* Move the args to their final destinations. */
601
for (i = 0; i < argreg; i++) {
602
/* None of these insns, including any spill code that might
603
be generated, may alter the condition codes. */
604
addInstr( env, mk_iMOVsd_RR( tmpregs[i], argregs[i] ) );
564
608
/* Finally, the call itself. */
565
610
addInstr(env, AMD64Instr_Call(
567
612
Ptr_to_ULong(cee->addr),
841
886
AMD64AluOp aluOp;
842
887
AMD64ShiftOp shOp;
845
//.. /* Pattern: Sub32(0,x) */
846
//.. if (e->Iex.Binop.op == Iop_Sub32 && isZero32(e->Iex.Binop.arg1)) {
847
//.. HReg dst = newVRegI(env);
848
//.. HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2);
849
//.. addInstr(env, mk_iMOVsd_RR(reg,dst));
850
//.. addInstr(env, X86Instr_Unary32(Xun_NEG,X86RM_Reg(dst)));
889
/* Pattern: Sub64(0,x) */
890
/* and: Sub32(0,x) */
891
if ((e->Iex.Binop.op == Iop_Sub64 && isZeroU64(e->Iex.Binop.arg1))
892
|| (e->Iex.Binop.op == Iop_Sub32 && isZeroU32(e->Iex.Binop.arg1))) {
893
HReg dst = newVRegI(env);
894
HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2);
895
addInstr(env, mk_iMOVsd_RR(reg,dst));
896
addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst));
854
900
/* Is it an addition or logical style op? */
855
901
switch (e->Iex.Binop.op) {
856
902
case Iop_Add8: case Iop_Add16: case Iop_Add32: case Iop_Add64:
1449
1511
AMD64RMI_Reg(tmp), dst));
1456
HReg dst = newVRegI(env);
1457
HReg reg = iselIntExpr_R(env, e->Iex.Unop.arg);
1458
addInstr(env, mk_iMOVsd_RR(reg,dst));
1459
addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst));
1515
case Iop_CmpwNEZ64: {
1516
HReg dst = newVRegI(env);
1517
HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1518
addInstr(env, mk_iMOVsd_RR(src,dst));
1519
addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst));
1520
addInstr(env, AMD64Instr_Alu64R(Aalu_OR,
1521
AMD64RMI_Reg(src), dst));
1522
addInstr(env, AMD64Instr_Sh64(Ash_SAR, 63, dst));
1526
case Iop_CmpwNEZ32: {
1527
HReg src = newVRegI(env);
1528
HReg dst = newVRegI(env);
1529
HReg pre = iselIntExpr_R(env, e->Iex.Unop.arg);
1530
addInstr(env, mk_iMOVsd_RR(pre,src));
1531
addInstr(env, AMD64Instr_MovZLQ(src,src));
1532
addInstr(env, mk_iMOVsd_RR(src,dst));
1533
addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst));
1534
addInstr(env, AMD64Instr_Alu64R(Aalu_OR,
1535
AMD64RMI_Reg(src), dst));
1536
addInstr(env, AMD64Instr_Sh64(Ash_SAR, 63, dst));
1544
HReg dst = newVRegI(env);
1545
HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1546
addInstr(env, mk_iMOVsd_RR(src, dst));
1547
addInstr(env, AMD64Instr_Unary64(Aun_NEG, dst));
1548
addInstr(env, AMD64Instr_Alu64R(Aalu_OR, AMD64RMI_Reg(src), dst));
1965
2054
static AMD64CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
1968
//.. DECLARE_PATTERN(p_1Uto32_then_32to1);
1969
//.. DECLARE_PATTERN(p_1Sto32_then_32to1);
1971
DECLARE_PATTERN(p_1Uto64_then_64to1);
1974
2059
vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
1977
if (e->tag == Iex_Tmp) {
1978
HReg r64 = lookupIRTemp(env, e->Iex.Tmp.tmp);
2062
if (e->tag == Iex_RdTmp) {
2063
HReg r64 = lookupIRTemp(env, e->Iex.RdTmp.tmp);
1979
2064
HReg dst = newVRegI(env);
1980
2065
addInstr(env, mk_iMOVsd_RR(r64,dst));
1981
2066
addInstr(env, AMD64Instr_Alu64R(Aalu_AND,AMD64RMI_Imm(1),dst));
2003
2088
/* --- patterns rooted at: 64to1 --- */
2005
/* 64to1(1Uto64(expr1)) ==> expr1 */
2006
DEFINE_PATTERN( p_1Uto64_then_64to1,
2007
unop(Iop_64to1, unop(Iop_1Uto64, bind(0))) );
2008
if (matchIRExpr(&mi,p_1Uto64_then_64to1,e)) {
2009
IRExpr* expr1 = mi.bindee[0];
2010
return iselCondCode(env, expr1);
2013
//.. /* 32to1(1Uto32(expr1)) -- the casts are pointless, ignore them */
2014
//.. DEFINE_PATTERN(p_1Uto32_then_32to1,
2015
//.. unop(Iop_32to1,unop(Iop_1Uto32,bind(0))));
2016
//.. if (matchIRExpr(&mi,p_1Uto32_then_32to1,e)) {
2017
//.. IRExpr* expr1 = mi.bindee[0];
2018
//.. return iselCondCode(env, expr1);
2021
//.. /* 32to1(1Sto32(expr1)) -- the casts are pointless, ignore them */
2022
//.. DEFINE_PATTERN(p_1Sto32_then_32to1,
2023
//.. unop(Iop_32to1,unop(Iop_1Sto32,bind(0))));
2024
//.. if (matchIRExpr(&mi,p_1Sto32_then_32to1,e)) {
2025
//.. IRExpr* expr1 = mi.bindee[0];
2026
//.. return iselCondCode(env, expr1);
2030
2091
if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_64to1) {
2031
2092
HReg reg = iselIntExpr_R(env, e->Iex.Unop.arg);
2171
//.. /* CmpNE64(1Sto64(b), 0) ==> b */
2173
//.. DECLARE_PATTERN(p_CmpNE64_1Sto64);
2174
//.. DEFINE_PATTERN(
2175
//.. p_CmpNE64_1Sto64,
2176
//.. binop(Iop_CmpNE64, unop(Iop_1Sto64,bind(0)), mkU64(0)));
2177
//.. if (matchIRExpr(&mi, p_CmpNE64_1Sto64, e)) {
2178
//.. return iselCondCode(env, mi.bindee[0]);
2182
//.. /* CmpNE64(x, 0) */
2184
//.. DECLARE_PATTERN(p_CmpNE64_x_zero);
2185
//.. DEFINE_PATTERN(
2186
//.. p_CmpNE64_x_zero,
2187
//.. binop(Iop_CmpNE64, bind(0), mkU64(0)) );
2188
//.. if (matchIRExpr(&mi, p_CmpNE64_x_zero, e)) {
2190
//.. IRExpr* x = mi.bindee[0];
2191
//.. HReg tmp = newVRegI(env);
2192
//.. iselInt64Expr( &hi, &lo, env, x );
2193
//.. addInstr(env, mk_iMOVsd_RR(hi, tmp));
2194
//.. addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(lo), tmp));
2200
//.. if (e->tag == Iex_Binop
2201
//.. && e->Iex.Binop.op == Iop_CmpNE64) {
2202
//.. HReg hi1, hi2, lo1, lo2;
2203
//.. HReg tHi = newVRegI(env);
2204
//.. HReg tLo = newVRegI(env);
2205
//.. iselInt64Expr( &hi1, &lo1, env, e->Iex.Binop.arg1 );
2206
//.. iselInt64Expr( &hi2, &lo2, env, e->Iex.Binop.arg2 );
2207
//.. addInstr(env, mk_iMOVsd_RR(hi1, tHi));
2208
//.. addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(hi2), tHi));
2209
//.. addInstr(env, mk_iMOVsd_RR(lo1, tLo));
2210
//.. addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(lo2), tLo));
2211
//.. addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(tHi), tLo));
2212
//.. switch (e->Iex.Binop.op) {
2213
//.. case Iop_CmpNE64: return Xcc_NZ;
2214
//.. default: vpanic("iselCondCode(x86): CmpXX64");
2219
2233
vpanic("iselCondCode(amd64)");
3543
3556
if (tya != Ity_I64 || end != Iend_LE)
3544
3557
goto stmt_fail;
3546
am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3547
3559
if (tyd == Ity_I64) {
3560
AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3548
3561
AMD64RI* ri = iselIntExpr_RI(env, stmt->Ist.Store.data);
3549
3562
addInstr(env, AMD64Instr_Alu64M(Aalu_MOV,ri,am));
3552
3565
if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32) {
3566
AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3553
3567
HReg r = iselIntExpr_R(env, stmt->Ist.Store.data);
3554
3568
addInstr(env, AMD64Instr_Store(
3555
3569
toUChar(tyd==Ity_I8 ? 1 : (tyd==Ity_I16 ? 2 : 4)),
3559
3573
if (tyd == Ity_F64) {
3574
AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3560
3575
HReg r = iselDblExpr(env, stmt->Ist.Store.data);
3561
3576
addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, r, am));
3564
3579
if (tyd == Ity_F32) {
3580
AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3565
3581
HReg r = iselFltExpr(env, stmt->Ist.Store.data);
3566
3582
addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 4, r, am));
3569
//.. if (tyd == Ity_I64) {
3570
//.. HReg vHi, vLo, rA;
3571
//.. iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Store.data);
3572
//.. rA = iselIntExpr_R(env, stmt->Ist.Store.addr);
3573
//.. addInstr(env, X86Instr_Alu32M(
3574
//.. Xalu_MOV, X86RI_Reg(vLo), X86AMode_IR(0, rA)));
3575
//.. addInstr(env, X86Instr_Alu32M(
3576
//.. Xalu_MOV, X86RI_Reg(vHi), X86AMode_IR(4, rA)));
3579
3585
if (tyd == Ity_V128) {
3586
AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3580
3587
HReg r = iselVecExpr(env, stmt->Ist.Store.data);
3581
3588
addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, r, am));
3662
3669
/* --------- TMP --------- */
3664
IRTemp tmp = stmt->Ist.Tmp.tmp;
3671
IRTemp tmp = stmt->Ist.WrTmp.tmp;
3665
3672
IRType ty = typeOfIRTemp(env->type_env, tmp);
3674
/* optimisation: if stmt->Ist.WrTmp.data is Add64(..,..),
3675
compute it into an AMode and then use LEA. This usually
3676
produces fewer instructions, often because (for memcheck
3677
created IR) we get t = address-expression, (t is later used
3678
twice) and so doing this naturally turns address-expression
3679
back into an AMD64 amode. */
3681
&& stmt->Ist.WrTmp.data->tag == Iex_Binop
3682
&& stmt->Ist.WrTmp.data->Iex.Binop.op == Iop_Add64) {
3683
AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.WrTmp.data);
3684
HReg dst = lookupIRTemp(env, tmp);
3685
if (am->tag == Aam_IR && am->Aam.IR.imm == 0) {
3686
/* Hmm, iselIntExpr_AMode wimped out and just computed the
3687
value into a register. Just emit a normal reg-reg move
3688
so reg-alloc can coalesce it away in the usual way. */
3689
HReg src = am->Aam.IR.reg;
3690
addInstr(env, AMD64Instr_Alu64R(Aalu_MOV, AMD64RMI_Reg(src), dst));
3692
addInstr(env, AMD64Instr_Lea64(am,dst));
3666
3697
if (ty == Ity_I64 || ty == Ity_I32
3667
3698
|| ty == Ity_I16 || ty == Ity_I8) {
3668
AMD64RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.Tmp.data);
3699
AMD64RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.WrTmp.data);
3669
3700
HReg dst = lookupIRTemp(env, tmp);
3670
3701
addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,rmi,dst));
3673
3704
if (ty == Ity_I128) {
3674
3705
HReg rHi, rLo, dstHi, dstLo;
3675
iselInt128Expr(&rHi,&rLo, env, stmt->Ist.Tmp.data);
3706
iselInt128Expr(&rHi,&rLo, env, stmt->Ist.WrTmp.data);
3676
3707
lookupIRTemp128( &dstHi, &dstLo, env, tmp);
3677
3708
addInstr(env, mk_iMOVsd_RR(rHi,dstHi) );
3678
3709
addInstr(env, mk_iMOVsd_RR(rLo,dstLo) );
3681
3712
if (ty == Ity_I1) {
3682
AMD64CondCode cond = iselCondCode(env, stmt->Ist.Tmp.data);
3713
AMD64CondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data);
3683
3714
HReg dst = lookupIRTemp(env, tmp);
3684
3715
addInstr(env, AMD64Instr_Set64(cond, dst));
3687
3718
if (ty == Ity_F64) {
3688
3719
HReg dst = lookupIRTemp(env, tmp);
3689
HReg src = iselDblExpr(env, stmt->Ist.Tmp.data);
3720
HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
3690
3721
addInstr(env, mk_vMOVsd_RR(src, dst));
3693
3724
if (ty == Ity_F32) {
3694
3725
HReg dst = lookupIRTemp(env, tmp);
3695
HReg src = iselFltExpr(env, stmt->Ist.Tmp.data);
3726
HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
3696
3727
addInstr(env, mk_vMOVsd_RR(src, dst));
3699
3730
if (ty == Ity_V128) {
3700
3731
HReg dst = lookupIRTemp(env, tmp);
3701
HReg src = iselVecExpr(env, stmt->Ist.Tmp.data);
3732
HReg src = iselVecExpr(env, stmt->Ist.WrTmp.data);
3702
3733
addInstr(env, mk_vMOVsd_RR(src, dst));