~bkerensa/ubuntu/raring/valgrind/merge-from-deb

« back to all changes in this revision

Viewing changes to VEX/priv/host-amd64/isel.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrés Roldán
  • Date: 2008-06-13 02:31:40 UTC
  • mto: (1.4.1 upstream) (2.2.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: james.westby@ubuntu.com-20080613023140-iwk33rz9rhvfkr96
Import upstream version 3.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
   This file is part of LibVEX, a library for dynamic binary
11
11
   instrumentation and translation.
12
12
 
13
 
   Copyright (C) 2004-2006 OpenWorks LLP.  All rights reserved.
 
13
   Copyright (C) 2004-2007 OpenWorks LLP.  All rights reserved.
14
14
 
15
15
   This library is made available under a dual licensing scheme.
16
16
 
278
278
   return toBool(x == y1);
279
279
}
280
280
 
281
 
//.. /* Is this a 32-bit zero expression? */
282
 
//.. 
283
 
//.. static Bool isZero32 ( IRExpr* e )
284
 
//.. {
285
 
//..    return e->tag == Iex_Const
286
 
//..           && e->Iex.Const.con->tag == Ico_U32
287
 
//..           && e->Iex.Const.con->Ico.U32 == 0;
288
 
//.. }
 
281
/* Is this a 64-bit zero expression? */
 
282
 
 
283
static Bool isZeroU64 ( IRExpr* e )
 
284
{
 
285
   return e->tag == Iex_Const
 
286
          && e->Iex.Const.con->tag == Ico_U64
 
287
          && e->Iex.Const.con->Ico.U64 == 0ULL;
 
288
}
 
289
 
 
290
static Bool isZeroU32 ( IRExpr* e )
 
291
{
 
292
   return e->tag == Iex_Const
 
293
          && e->Iex.Const.con->tag == Ico_U32
 
294
          && e->Iex.Const.con->Ico.U32 == 0;
 
295
}
289
296
 
290
297
/* Make a int reg-reg move. */
291
298
 
365
372
//.. }
366
373
 
367
374
 
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).
372
 
*/
373
 
static
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
 
377
   NULL. */
 
378
 
 
379
static AMD64Instr* iselIntExpr_single_instruction ( ISelEnv* env,
 
380
                                                    HReg     dst,
 
381
                                                    IRExpr*  e )
375
382
{
376
 
   switch (e->tag) {
377
 
      case Iex_Tmp: case Iex_Const: case Iex_Get: 
378
 
         return False;
379
 
      default:
380
 
         return True;
381
 
   }
 
383
   vassert(typeOfIRExpr(env->type_env, e) == Ity_I64);
 
384
 
 
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(
 
389
                   Aalu_MOV,
 
390
                   AMD64RMI_Imm(toUInt(e->Iex.Const.con->Ico.U64)),
 
391
                   dst
 
392
                );
 
393
      } else {
 
394
         return AMD64Instr_Imm64(e->Iex.Const.con->Ico.U64, dst);
 
395
      }
 
396
   }
 
397
 
 
398
   if (e->tag == Iex_RdTmp) {
 
399
      HReg src = lookupIRTemp(env, e->Iex.RdTmp.tmp);
 
400
      return mk_iMOVsd_RR(src, dst);
 
401
   }
 
402
 
 
403
   if (e->tag == Iex_Get) {
 
404
      vassert(e->Iex.Get.ty == Ity_I64);
 
405
      return AMD64Instr_Alu64R(
 
406
                Aalu_MOV,
 
407
                AMD64RMI_Mem(
 
408
                   AMD64AMode_IR(e->Iex.Get.offset,
 
409
                                 hregAMD64_RBP())),
 
410
                dst);
 
411
   }
 
412
 
 
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);
 
418
   }
 
419
 
 
420
   if (0) { ppIRExpr(e); vex_printf("\n"); }
 
421
 
 
422
   return NULL;
382
423
}
383
424
 
384
425
 
394
435
   AMD64CondCode cc;
395
436
   HReg          argregs[6];
396
437
   HReg          tmpregs[6];
397
 
   Bool          go_fast;
 
438
   AMD64Instr*   fastinstrs[6];
398
439
   Int           n_args, i, argreg;
399
440
 
400
441
   /* Marshal args for a call and do the call.
464
505
   tmpregs[0] = tmpregs[1] = tmpregs[2] =
465
506
   tmpregs[3] = tmpregs[4] = tmpregs[5] = INVALID_HREG;
466
507
 
 
508
   fastinstrs[0] = fastinstrs[1] = fastinstrs[2] =
 
509
   fastinstrs[3] = fastinstrs[4] = fastinstrs[5] = NULL;
 
510
 
467
511
   /* First decide which scheme (slow or fast) is to be used.  First
468
512
      assume the fast scheme, and select slow if any contraindications
469
513
      (wow) appear. */
470
514
 
471
 
   go_fast = True;
472
 
 
473
515
   if (guard) {
474
516
      if (guard->tag == Iex_Const 
475
517
          && guard->Iex.Const.con->tag == Ico_U1
477
519
         /* unconditional */
478
520
      } else {
479
521
         /* Not manifestly unconditional -- be conservative. */
480
 
         go_fast = False;
481
 
      }
482
 
   }
483
 
 
484
 
   if (go_fast) {
485
 
      for (i = 0; i < n_args; i++) {
486
 
         if (mightRequireFixedRegs(args[i])) {
487
 
            go_fast = False;
488
 
            break;
489
 
         }
490
 
      }
491
 
   }
492
 
 
493
 
   /* At this point the scheme to use has been established.  Generate
494
 
      code to get the arg values into the argument rregs. */
495
 
 
496
 
   if (go_fast) {
497
 
 
498
 
      /* FAST SCHEME */
499
 
      argreg = 0;
500
 
      if (passBBP) {
501
 
         addInstr(env, mk_iMOVsd_RR( hregAMD64_RBP(), argregs[argreg]));
502
 
         argreg++;
503
 
      }
504
 
 
505
 
      for (i = 0; i < n_args; i++) {
506
 
         vassert(argreg < 6);
507
 
         vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
508
 
         addInstr(env, AMD64Instr_Alu64R(
509
 
                          Aalu_MOV, 
510
 
                          iselIntExpr_RMI(env, args[i]),
511
 
                          argregs[argreg]
512
 
                       )
513
 
                 );
514
 
         argreg++;
515
 
      }
516
 
 
517
 
      /* Fast scheme only applies for unconditional calls.  Hence: */
518
 
      cc = Acc_ALWAYS;
519
 
 
520
 
   } else {
521
 
 
522
 
      /* SLOW SCHEME; move via temporaries */
523
 
      argreg = 0;
524
 
 
525
 
      if (passBBP) {
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]));
530
 
         argreg++;
531
 
      }
532
 
 
533
 
      for (i = 0; i < n_args; i++) {
534
 
         vassert(argreg < 6);
535
 
         vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
536
 
         tmpregs[argreg] = iselIntExpr_R(env, args[i]);
537
 
         argreg++;
538
 
      }
539
 
 
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
543
 
         guard is 1:Bit. */
544
 
      cc = Acc_ALWAYS;
545
 
      if (guard) {
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 */
550
 
         } else {
551
 
            cc = iselCondCode( env, guard );
552
 
         }
553
 
      }
554
 
 
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] ) );
560
 
      }
561
 
 
562
 
   }
 
522
         goto slowscheme;
 
523
      }
 
524
   }
 
525
 
 
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. */
 
531
 
 
532
   /* FAST SCHEME */
 
533
   argreg = 0;
 
534
   if (passBBP) {
 
535
      fastinstrs[argreg] = mk_iMOVsd_RR( hregAMD64_RBP(), argregs[argreg]);
 
536
      argreg++;
 
537
   }
 
538
 
 
539
   for (i = 0; i < n_args; i++) {
 
540
      vassert(argreg < 6);
 
541
      vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
 
542
      fastinstrs[argreg] 
 
543
         = iselIntExpr_single_instruction( env, argregs[argreg], args[i] );
 
544
      if (fastinstrs[argreg] == NULL)
 
545
         goto slowscheme;
 
546
      argreg++;
 
547
   }
 
548
 
 
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]);
 
554
 
 
555
   /* Fast scheme only applies for unconditional calls.  Hence: */
 
556
   cc = Acc_ALWAYS;
 
557
 
 
558
   goto handle_call;
 
559
 
 
560
 
 
561
   /* SLOW SCHEME; move via temporaries */
 
562
  slowscheme:
 
563
#if 0
 
564
if (n_args > 0) {for (i = 0; args[i]; i++) {
 
565
ppIRExpr(args[i]); vex_printf(" "); }
 
566
vex_printf("\n");}
 
567
#endif
 
568
   argreg = 0;
 
569
 
 
570
   if (passBBP) {
 
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]));
 
575
      argreg++;
 
576
   }
 
577
 
 
578
   for (i = 0; i < n_args; i++) {
 
579
      vassert(argreg < 6);
 
580
      vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
 
581
      tmpregs[argreg] = iselIntExpr_R(env, args[i]);
 
582
      argreg++;
 
583
   }
 
584
 
 
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
 
588
      guard is 1:Bit. */
 
589
   cc = Acc_ALWAYS;
 
590
   if (guard) {
 
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 */
 
595
      } else {
 
596
         cc = iselCondCode( env, guard );
 
597
      }
 
598
   }
 
599
 
 
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] ) );
 
605
   }
 
606
 
563
607
 
564
608
   /* Finally, the call itself. */
 
609
  handle_call:
565
610
   addInstr(env, AMD64Instr_Call( 
566
611
                    cc, 
567
612
                    Ptr_to_ULong(cee->addr), 
576
621
   offset. */
577
622
 
578
623
static
579
 
AMD64AMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, 
 
624
AMD64AMode* genGuestArrayOffset ( ISelEnv* env, IRRegArray* descr, 
580
625
                                  IRExpr* off, Int bias )
581
626
{
582
627
   HReg tmp, roff;
804
849
   switch (e->tag) {
805
850
 
806
851
   /* --------- TEMP --------- */
807
 
   case Iex_Tmp: {
808
 
      return lookupIRTemp(env, e->Iex.Tmp.tmp);
 
852
   case Iex_RdTmp: {
 
853
      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
809
854
   }
810
855
 
811
856
   /* --------- LOAD --------- */
841
886
      AMD64AluOp   aluOp;
842
887
      AMD64ShiftOp shOp;
843
888
 
844
 
//.. 
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)));
851
 
//..          return dst;
852
 
//..       }
853
 
//.. 
 
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));
 
897
         return dst;
 
898
      }
 
899
 
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: 
992
1038
            fn = (HWord)h_generic_calc_InterleaveHI32x2; break;
993
1039
         case Iop_InterleaveLO32x2:
994
1040
            fn = (HWord)h_generic_calc_InterleaveLO32x2; break;
 
1041
         case Iop_CatOddLanes16x4:
 
1042
            fn = (HWord)h_generic_calc_CatOddLanes16x4; break;
 
1043
         case Iop_CatEvenLanes16x4:
 
1044
            fn = (HWord)h_generic_calc_CatEvenLanes16x4; break;
 
1045
         case Iop_Perm8x8:
 
1046
            fn = (HWord)h_generic_calc_Perm8x8; break;
995
1047
 
996
1048
         case Iop_Max8Ux8:
997
1049
            fn = (HWord)h_generic_calc_Max8Ux8; break;
1004
1056
 
1005
1057
         case Iop_Mul16x4:
1006
1058
            fn = (HWord)h_generic_calc_Mul16x4; break;
 
1059
         case Iop_Mul32x2:
 
1060
            fn = (HWord)h_generic_calc_Mul32x2; break;
1007
1061
         case Iop_MulHi16Sx4:
1008
1062
            fn = (HWord)h_generic_calc_MulHi16Sx4; break;
1009
1063
         case Iop_MulHi16Ux4:
1049
1103
            fn = (HWord)h_generic_calc_ShlN16x4;
1050
1104
            second_is_UInt = True;
1051
1105
            break;
 
1106
         case Iop_ShlN8x8:
 
1107
            fn = (HWord)h_generic_calc_ShlN8x8;
 
1108
            second_is_UInt = True;
 
1109
            break;
1052
1110
         case Iop_ShrN32x2:
1053
1111
            fn = (HWord)h_generic_calc_ShrN32x2; 
1054
1112
            second_is_UInt = True; 
1065
1123
            fn = (HWord)h_generic_calc_SarN16x4;
1066
1124
            second_is_UInt = True; 
1067
1125
            break;
 
1126
         case Iop_SarN8x8:
 
1127
            fn = (HWord)h_generic_calc_SarN8x8;
 
1128
            second_is_UInt = True; 
 
1129
            break;
1068
1130
 
1069
1131
         default:
1070
1132
            fn = (HWord)0; break;
1449
1511
                                            AMD64RMI_Reg(tmp), dst));
1450
1512
            return dst;
1451
1513
         }
1452
 
         case Iop_Neg8:
1453
 
         case Iop_Neg16:
1454
 
         case Iop_Neg32:
1455
 
         case Iop_Neg64: {
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));
 
1514
 
 
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));
 
1523
            return dst;
 
1524
         }
 
1525
 
 
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));
 
1537
            return dst;
 
1538
         }
 
1539
 
 
1540
         case Iop_Left8:
 
1541
         case Iop_Left16:
 
1542
         case Iop_Left32:
 
1543
         case Iop_Left64: {
 
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));
1460
1549
            return dst;
1461
1550
         }
1462
1551
 
1965
2054
static AMD64CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
1966
2055
{
1967
2056
   MatchInfo mi;
1968
 
//..    DECLARE_PATTERN(p_1Uto32_then_32to1);
1969
 
//..    DECLARE_PATTERN(p_1Sto32_then_32to1);
1970
 
 
1971
 
   DECLARE_PATTERN(p_1Uto64_then_64to1);
1972
2057
 
1973
2058
   vassert(e);
1974
2059
   vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
1975
2060
 
1976
2061
   /* var */
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));
2002
2087
 
2003
2088
   /* --- patterns rooted at: 64to1 --- */
2004
2089
 
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);
2011
 
   }
2012
 
 
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);
2019
 
//..    }
2020
 
//.. 
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);
2027
 
//..    }
2028
 
 
2029
2090
   /* 64to1 */
2030
2091
   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_64to1) {
2031
2092
      HReg reg = iselIntExpr_R(env, e->Iex.Unop.arg);
2168
2229
      }
2169
2230
   }
2170
2231
 
2171
 
//..    /* CmpNE64(1Sto64(b), 0) ==> b */
2172
 
//..    {
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]);
2179
 
//..       }
2180
 
//..    }
2181
 
//.. 
2182
 
//..    /* CmpNE64(x, 0) */
2183
 
//..    {
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)) {
2189
 
//..          HReg hi, lo;
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));
2195
 
//..          return Xcc_NZ;
2196
 
//..       }
2197
 
//..    }
2198
 
//.. 
2199
 
//..    /* CmpNE64 */
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");
2215
 
//..       }
2216
 
//..    }
2217
 
 
2218
2232
   ppIRExpr(e);
2219
2233
   vpanic("iselCondCode(amd64)");
2220
2234
}
2266
2280
//..    }
2267
2281
 
2268
2282
   /* read 128-bit IRTemp */
2269
 
   if (e->tag == Iex_Tmp) {
2270
 
      lookupIRTemp128( rHi, rLo, env, e->Iex.Tmp.tmp);
 
2283
   if (e->tag == Iex_RdTmp) {
 
2284
      lookupIRTemp128( rHi, rLo, env, e->Iex.RdTmp.tmp);
2271
2285
      return;
2272
2286
   }
2273
2287
 
2685
2699
   IRType ty = typeOfIRExpr(env->type_env,e);
2686
2700
   vassert(ty == Ity_F32);
2687
2701
 
2688
 
   if (e->tag == Iex_Tmp) {
2689
 
      return lookupIRTemp(env, e->Iex.Tmp.tmp);
 
2702
   if (e->tag == Iex_RdTmp) {
 
2703
      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2690
2704
   }
2691
2705
 
2692
2706
   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
2782
2796
   vassert(e);
2783
2797
   vassert(ty == Ity_F64);
2784
2798
 
2785
 
   if (e->tag == Iex_Tmp) {
2786
 
      return lookupIRTemp(env, e->Iex.Tmp.tmp);
 
2799
   if (e->tag == Iex_RdTmp) {
 
2800
      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2787
2801
   }
2788
2802
 
2789
2803
   if (e->tag == Iex_Const) {
3097
3111
   vassert(e);
3098
3112
   vassert(ty == Ity_V128);
3099
3113
 
3100
 
   if (e->tag == Iex_Tmp) {
3101
 
      return lookupIRTemp(env, e->Iex.Tmp.tmp);
 
3114
   if (e->tag == Iex_RdTmp) {
 
3115
      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3102
3116
   }
3103
3117
 
3104
3118
   if (e->tag == Iex_Get) {
3535
3549
 
3536
3550
   /* --------- STORE --------- */
3537
3551
   case Ist_Store: {
3538
 
      AMD64AMode* am;
3539
3552
      IRType    tya = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
3540
3553
      IRType    tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
3541
3554
      IREndness end = stmt->Ist.Store.end;
3543
3556
      if (tya != Ity_I64 || end != Iend_LE) 
3544
3557
         goto stmt_fail;
3545
3558
 
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));
3550
3563
         return;
3551
3564
      }
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)),
3557
3571
         return;
3558
3572
      }
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));
3562
3577
         return;
3563
3578
      }
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));
3567
3583
         return;
3568
3584
      }
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)));
3577
 
//..          return;
3578
 
//..       }
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));
3582
3589
         return;
3660
3667
   }
3661
3668
 
3662
3669
   /* --------- TMP --------- */
3663
 
   case Ist_Tmp: {
3664
 
      IRTemp tmp = stmt->Ist.Tmp.tmp;
 
3670
   case Ist_WrTmp: {
 
3671
      IRTemp tmp = stmt->Ist.WrTmp.tmp;
3665
3672
      IRType ty = typeOfIRTemp(env->type_env, tmp);
 
3673
 
 
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. */
 
3680
      if (ty == Ity_I64 
 
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));
 
3691
         } else {
 
3692
            addInstr(env, AMD64Instr_Lea64(am,dst));
 
3693
         }
 
3694
         return;
 
3695
      }
 
3696
 
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));
3671
3702
         return;
3672
3703
      }
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) );
3679
3710
         return;
3680
3711
      }
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));
3685
3716
         return;
3686
3717
      }
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));
3691
3722
         return;
3692
3723
      }
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));
3697
3728
         return;
3698
3729
      }
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));
3703
3734
         return;
3704
3735
      }
3737
3768
   }
3738
3769
 
3739
3770
   /* --------- MEM FENCE --------- */
3740
 
   case Ist_MFence:
3741
 
      addInstr(env, AMD64Instr_MFence());
3742
 
      return;
 
3771
   case Ist_MBE:
 
3772
      switch (stmt->Ist.MBE.event) {
 
3773
         case Imbe_Fence:
 
3774
            addInstr(env, AMD64Instr_MFence());
 
3775
            return;
 
3776
         case Imbe_BusLock:
 
3777
         case Imbe_BusUnlock:
 
3778
            return;
 
3779
         default:
 
3780
            break;
 
3781
      }
 
3782
      break;
3743
3783
 
3744
3784
   /* --------- INSTR MARK --------- */
3745
3785
   /* Doesn't generate any executable code ... */
3799
3839
/*--- Insn selector top-level                           ---*/
3800
3840
/*---------------------------------------------------------*/
3801
3841
 
3802
 
/* Translate an entire BB to amd64 code. */
 
3842
/* Translate an entire SB to amd64 code. */
3803
3843
 
3804
 
HInstrArray* iselBB_AMD64 ( IRBB* bb, VexArch arch_host,
3805
 
                                      VexArchInfo* archinfo_host )
 
3844
HInstrArray* iselSB_AMD64 ( IRSB* bb, VexArch      arch_host,
 
3845
                                      VexArchInfo* archinfo_host,
 
3846
                                      VexAbiInfo*  vbi/*UNUSED*/ )
3806
3847
{
3807
3848
   Int      i, j;
3808
3849
   HReg     hreg, hregHI;