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

« back to all changes in this revision

Viewing changes to VEX/priv/host_x86_isel.c

  • Committer: Benjamin Kerensa
  • Date: 2012-11-21 23:57:58 UTC
  • mfrom: (1.1.16)
  • Revision ID: bkerensa@ubuntu.com-20121121235758-bd1rv5uc5vzov2p6
Merge from debian unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
   This file is part of Valgrind, a dynamic binary instrumentation
8
8
   framework.
9
9
 
10
 
   Copyright (C) 2004-2011 OpenWorks LLP
 
10
   Copyright (C) 2004-2012 OpenWorks LLP
11
11
      info@open-works.net
12
12
 
13
13
   This program is free software; you can redistribute it and/or
154
154
   - The host subarchitecture we are selecting insns for.  
155
155
     This is set at the start and does not change.
156
156
 
157
 
   Note, this is all host-independent.  */
 
157
   - A Bool for indicating whether we may generate chain-me
 
158
     instructions for control flow transfers, or whether we must use
 
159
     XAssisted.
 
160
 
 
161
   - The maximum guest address of any guest insn in this block.
 
162
     Actually, the address of the highest-addressed byte from any insn
 
163
     in this block.  Is set at the start and does not change.  This is
 
164
     used for detecting jumps which are definitely forward-edges from
 
165
     this block, and therefore can be made (chained) to the fast entry
 
166
     point of the destination, thereby avoiding the destination's
 
167
     event check.
 
168
 
 
169
   Note, this is all (well, mostly) host-independent.
 
170
*/
158
171
 
159
172
typedef
160
173
   struct {
 
174
      /* Constant -- are set at the start and do not change. */
161
175
      IRTypeEnv*   type_env;
162
176
 
163
177
      HReg*        vregmap;
164
178
      HReg*        vregmapHI;
165
179
      Int          n_vregmap;
166
180
 
 
181
      UInt         hwcaps;
 
182
 
 
183
      Bool         chainingAllowed;
 
184
      Addr64       max_ga;
 
185
 
 
186
      /* These are modified as we go along. */
167
187
      HInstrArray* code;
168
 
 
169
188
      Int          vreg_ctr;
170
 
 
171
 
      UInt         hwcaps;
172
189
   }
173
190
   ISelEnv;
174
191
 
772
789
 
773
790
   /* --------- TERNARY OP --------- */
774
791
   case Iex_Triop: {
 
792
      IRTriop *triop = e->Iex.Triop.details;
775
793
      /* C3210 flags following FPU partial remainder (fprem), both
776
794
         IEEE compliant (PREM1) and non-IEEE compliant (PREM). */
777
 
      if (e->Iex.Triop.op == Iop_PRemC3210F64
778
 
          || e->Iex.Triop.op == Iop_PRem1C3210F64) {
 
795
      if (triop->op == Iop_PRemC3210F64
 
796
          || triop->op == Iop_PRem1C3210F64) {
779
797
         HReg junk = newVRegF(env);
780
798
         HReg dst  = newVRegI(env);
781
 
         HReg srcL = iselDblExpr(env, e->Iex.Triop.arg2);
782
 
         HReg srcR = iselDblExpr(env, e->Iex.Triop.arg3);
 
799
         HReg srcL = iselDblExpr(env, triop->arg2);
 
800
         HReg srcR = iselDblExpr(env, triop->arg3);
783
801
         /* XXXROUNDINGFIXME */
784
802
         /* set roundingmode here */
785
803
         addInstr(env, X86Instr_FpBinary(
2941
2959
 
2942
2960
   if (e->tag == Iex_Triop) {
2943
2961
      X86FpOp fpop = Xfp_INVALID;
2944
 
      switch (e->Iex.Triop.op) {
 
2962
      IRTriop *triop = e->Iex.Triop.details;
 
2963
      switch (triop->op) {
2945
2964
         case Iop_AddF64:    fpop = Xfp_ADD; break;
2946
2965
         case Iop_SubF64:    fpop = Xfp_SUB; break;
2947
2966
         case Iop_MulF64:    fpop = Xfp_MUL; break;
2956
2975
      }
2957
2976
      if (fpop != Xfp_INVALID) {
2958
2977
         HReg res  = newVRegF(env);
2959
 
         HReg srcL = iselDblExpr(env, e->Iex.Triop.arg2);
2960
 
         HReg srcR = iselDblExpr(env, e->Iex.Triop.arg3);
 
2978
         HReg srcL = iselDblExpr(env, triop->arg2);
 
2979
         HReg srcR = iselDblExpr(env, triop->arg3);
2961
2980
         /* XXXROUNDINGFIXME */
2962
2981
         /* set roundingmode here */
2963
2982
         addInstr(env, X86Instr_FpBinary(fpop,srcL,srcR,res));
3813
3832
 
3814
3833
   /* --------- Indexed PUT --------- */
3815
3834
   case Ist_PutI: {
 
3835
      IRPutI *puti = stmt->Ist.PutI.details;
 
3836
 
3816
3837
      X86AMode* am 
3817
3838
         = genGuestArrayOffset(
3818
 
              env, stmt->Ist.PutI.descr, 
3819
 
                   stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
 
3839
              env, puti->descr, 
 
3840
                   puti->ix, puti->bias );
3820
3841
 
3821
 
      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
 
3842
      IRType ty = typeOfIRExpr(env->type_env, puti->data);
3822
3843
      if (ty == Ity_F64) {
3823
 
         HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
 
3844
         HReg val = iselDblExpr(env, puti->data);
3824
3845
         addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, val, am ));
3825
3846
         return;
3826
3847
      }
3827
3848
      if (ty == Ity_I8) {
3828
 
         HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
 
3849
         HReg r = iselIntExpr_R(env, puti->data);
3829
3850
         addInstr(env, X86Instr_Store( 1, r, am ));
3830
3851
         return;
3831
3852
      }
3832
3853
      if (ty == Ity_I32) {
3833
 
         HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
 
3854
         HReg r = iselIntExpr_R(env, puti->data);
3834
3855
         addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(r), am ));
3835
3856
         return;
3836
3857
      }
3837
3858
      if (ty == Ity_I64) {
3838
3859
         HReg rHi, rLo;
3839
3860
         X86AMode* am4 = advance4(am);
3840
 
         iselInt64Expr(&rHi, &rLo, env, stmt->Ist.PutI.data);
 
3861
         iselInt64Expr(&rHi, &rLo, env, puti->data);
3841
3862
         addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rLo), am ));
3842
3863
         addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rHi), am4 ));
3843
3864
         return;
4038
4059
 
4039
4060
   /* --------- EXIT --------- */
4040
4061
   case Ist_Exit: {
4041
 
      X86RI*      dst;
4042
 
      X86CondCode cc;
4043
4062
      if (stmt->Ist.Exit.dst->tag != Ico_U32)
4044
 
         vpanic("isel_x86: Ist_Exit: dst is not a 32-bit value");
4045
 
      dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst));
4046
 
      cc  = iselCondCode(env,stmt->Ist.Exit.guard);
4047
 
      addInstr(env, X86Instr_Goto(stmt->Ist.Exit.jk, cc, dst));
4048
 
      return;
 
4063
         vpanic("iselStmt(x86): Ist_Exit: dst is not a 32-bit value");
 
4064
 
 
4065
      X86CondCode cc    = iselCondCode(env, stmt->Ist.Exit.guard);
 
4066
      X86AMode*   amEIP = X86AMode_IR(stmt->Ist.Exit.offsIP,
 
4067
                                      hregX86_EBP());
 
4068
 
 
4069
      /* Case: boring transfer to known address */
 
4070
      if (stmt->Ist.Exit.jk == Ijk_Boring) {
 
4071
         if (env->chainingAllowed) {
 
4072
            /* .. almost always true .. */
 
4073
            /* Skip the event check at the dst if this is a forwards
 
4074
               edge. */
 
4075
            Bool toFastEP
 
4076
               = ((Addr32)stmt->Ist.Exit.dst->Ico.U32) > env->max_ga;
 
4077
            if (0) vex_printf("%s", toFastEP ? "Y" : ",");
 
4078
            addInstr(env, X86Instr_XDirect(stmt->Ist.Exit.dst->Ico.U32,
 
4079
                                           amEIP, cc, toFastEP));
 
4080
         } else {
 
4081
            /* .. very occasionally .. */
 
4082
            /* We can't use chaining, so ask for an assisted transfer,
 
4083
               as that's the only alternative that is allowable. */
 
4084
            HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
 
4085
            addInstr(env, X86Instr_XAssisted(r, amEIP, cc, Ijk_Boring));
 
4086
         }
 
4087
         return;
 
4088
      }
 
4089
 
 
4090
      /* Case: assisted transfer to arbitrary address */
 
4091
      switch (stmt->Ist.Exit.jk) {
 
4092
         /* Keep this list in sync with that in iselNext below */
 
4093
         case Ijk_ClientReq:
 
4094
         case Ijk_EmWarn:
 
4095
         case Ijk_MapFail:
 
4096
         case Ijk_NoDecode:
 
4097
         case Ijk_NoRedir:
 
4098
         case Ijk_SigSEGV:
 
4099
         case Ijk_SigTRAP:
 
4100
         case Ijk_Sys_int128:
 
4101
         case Ijk_Sys_int129:
 
4102
         case Ijk_Sys_int130:
 
4103
         case Ijk_Sys_sysenter:
 
4104
         case Ijk_TInval:
 
4105
         case Ijk_Yield:
 
4106
         {
 
4107
            HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
 
4108
            addInstr(env, X86Instr_XAssisted(r, amEIP, cc, stmt->Ist.Exit.jk));
 
4109
            return;
 
4110
         }
 
4111
         default:
 
4112
            break;
 
4113
      }
 
4114
 
 
4115
      /* Do we ever expect to see any other kind? */
 
4116
      goto stmt_fail;
4049
4117
   }
4050
4118
 
4051
4119
   default: break;
4060
4128
/*--- ISEL: Basic block terminators (Nexts)             ---*/
4061
4129
/*---------------------------------------------------------*/
4062
4130
 
4063
 
static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk )
 
4131
static void iselNext ( ISelEnv* env,
 
4132
                       IRExpr* next, IRJumpKind jk, Int offsIP )
4064
4133
{
4065
 
   X86RI* ri;
4066
4134
   if (vex_traceflags & VEX_TRACE_VCODE) {
4067
 
      vex_printf("\n-- goto {");
 
4135
      vex_printf( "\n-- PUT(%d) = ", offsIP);
 
4136
      ppIRExpr( next );
 
4137
      vex_printf( "; exit-");
4068
4138
      ppIRJumpKind(jk);
4069
 
      vex_printf("} ");
4070
 
      ppIRExpr(next);
4071
 
      vex_printf("\n");
4072
 
   }
4073
 
   ri = iselIntExpr_RI(env, next);
4074
 
   addInstr(env, X86Instr_Goto(jk, Xcc_ALWAYS,ri));
 
4139
      vex_printf( "\n");
 
4140
   }
 
4141
 
 
4142
   /* Case: boring transfer to known address */
 
4143
   if (next->tag == Iex_Const) {
 
4144
      IRConst* cdst = next->Iex.Const.con;
 
4145
      vassert(cdst->tag == Ico_U32);
 
4146
      if (jk == Ijk_Boring || jk == Ijk_Call) {
 
4147
         /* Boring transfer to known address */
 
4148
         X86AMode* amEIP = X86AMode_IR(offsIP, hregX86_EBP());
 
4149
         if (env->chainingAllowed) {
 
4150
            /* .. almost always true .. */
 
4151
            /* Skip the event check at the dst if this is a forwards
 
4152
               edge. */
 
4153
            Bool toFastEP
 
4154
               = ((Addr64)cdst->Ico.U32) > env->max_ga;
 
4155
            if (0) vex_printf("%s", toFastEP ? "X" : ".");
 
4156
            addInstr(env, X86Instr_XDirect(cdst->Ico.U32,
 
4157
                                           amEIP, Xcc_ALWAYS, 
 
4158
                                           toFastEP));
 
4159
         } else {
 
4160
            /* .. very occasionally .. */
 
4161
            /* We can't use chaining, so ask for an assisted transfer,
 
4162
               as that's the only alternative that is allowable. */
 
4163
            HReg r = iselIntExpr_R(env, next);
 
4164
            addInstr(env, X86Instr_XAssisted(r, amEIP, Xcc_ALWAYS,
 
4165
                                             Ijk_Boring));
 
4166
         }
 
4167
         return;
 
4168
      }
 
4169
   }
 
4170
 
 
4171
   /* Case: call/return (==boring) transfer to any address */
 
4172
   switch (jk) {
 
4173
      case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
 
4174
         HReg      r     = iselIntExpr_R(env, next);
 
4175
         X86AMode* amEIP = X86AMode_IR(offsIP, hregX86_EBP());
 
4176
         if (env->chainingAllowed) {
 
4177
            addInstr(env, X86Instr_XIndir(r, amEIP, Xcc_ALWAYS));
 
4178
         } else {
 
4179
            addInstr(env, X86Instr_XAssisted(r, amEIP, Xcc_ALWAYS,
 
4180
                                               Ijk_Boring));
 
4181
         }
 
4182
         return;
 
4183
      }
 
4184
      default:
 
4185
         break;
 
4186
   }
 
4187
 
 
4188
   /* Case: assisted transfer to arbitrary address */
 
4189
   switch (jk) {
 
4190
      /* Keep this list in sync with that for Ist_Exit above */
 
4191
      case Ijk_ClientReq:
 
4192
      case Ijk_EmWarn:
 
4193
      case Ijk_MapFail:
 
4194
      case Ijk_NoDecode:
 
4195
      case Ijk_NoRedir:
 
4196
      case Ijk_SigSEGV:
 
4197
      case Ijk_SigTRAP:
 
4198
      case Ijk_Sys_int128:
 
4199
      case Ijk_Sys_int129:
 
4200
      case Ijk_Sys_int130:
 
4201
      case Ijk_Sys_sysenter:
 
4202
      case Ijk_TInval:
 
4203
      case Ijk_Yield:
 
4204
      {
 
4205
         HReg      r     = iselIntExpr_R(env, next);
 
4206
         X86AMode* amEIP = X86AMode_IR(offsIP, hregX86_EBP());
 
4207
         addInstr(env, X86Instr_XAssisted(r, amEIP, Xcc_ALWAYS, jk));
 
4208
         return;
 
4209
      }
 
4210
      default:
 
4211
         break;
 
4212
   }
 
4213
 
 
4214
   vex_printf( "\n-- PUT(%d) = ", offsIP);
 
4215
   ppIRExpr( next );
 
4216
   vex_printf( "; exit-");
 
4217
   ppIRJumpKind(jk);
 
4218
   vex_printf( "\n");
 
4219
   vassert(0); // are we expecting any other kind?
4075
4220
}
4076
4221
 
4077
4222
 
4081
4226
 
4082
4227
/* Translate an entire SB to x86 code. */
4083
4228
 
4084
 
HInstrArray* iselSB_X86 ( IRSB* bb, VexArch      arch_host,
4085
 
                                    VexArchInfo* archinfo_host,
4086
 
                                    VexAbiInfo*  vbi/*UNUSED*/ )
 
4229
HInstrArray* iselSB_X86 ( IRSB* bb,
 
4230
                          VexArch      arch_host,
 
4231
                          VexArchInfo* archinfo_host,
 
4232
                          VexAbiInfo*  vbi/*UNUSED*/,
 
4233
                          Int offs_Host_EvC_Counter,
 
4234
                          Int offs_Host_EvC_FailAddr,
 
4235
                          Bool chainingAllowed,
 
4236
                          Bool addProfInc,
 
4237
                          Addr64 max_ga )
4087
4238
{
4088
4239
   Int      i, j;
4089
4240
   HReg     hreg, hregHI;
4090
4241
   ISelEnv* env;
4091
4242
   UInt     hwcaps_host = archinfo_host->hwcaps;
 
4243
   X86AMode *amCounter, *amFailAddr;
4092
4244
 
4093
4245
   /* sanity ... */
4094
4246
   vassert(arch_host == VexArchX86);
4097
4249
                     | VEX_HWCAPS_X86_SSE2
4098
4250
                     | VEX_HWCAPS_X86_SSE3
4099
4251
                     | VEX_HWCAPS_X86_LZCNT)));
 
4252
   vassert(sizeof(max_ga) == 8);
 
4253
   vassert((max_ga >> 32) == 0);
4100
4254
 
4101
4255
   /* Make up an initial environment to use. */
4102
4256
   env = LibVEX_Alloc(sizeof(ISelEnv));
4115
4269
   env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
4116
4270
 
4117
4271
   /* and finally ... */
4118
 
   env->hwcaps = hwcaps_host;
 
4272
   env->chainingAllowed = chainingAllowed;
 
4273
   env->hwcaps          = hwcaps_host;
 
4274
   env->max_ga          = max_ga;
4119
4275
 
4120
4276
   /* For each IR temporary, allocate a suitably-kinded virtual
4121
4277
      register. */
4140
4296
   }
4141
4297
   env->vreg_ctr = j;
4142
4298
 
 
4299
   /* The very first instruction must be an event check. */
 
4300
   amCounter  = X86AMode_IR(offs_Host_EvC_Counter,  hregX86_EBP());
 
4301
   amFailAddr = X86AMode_IR(offs_Host_EvC_FailAddr, hregX86_EBP());
 
4302
   addInstr(env, X86Instr_EvCheck(amCounter, amFailAddr));
 
4303
 
 
4304
   /* Possibly a block counter increment (for profiling).  At this
 
4305
      point we don't know the address of the counter, so just pretend
 
4306
      it is zero.  It will have to be patched later, but before this
 
4307
      translation is used, by a call to LibVEX_patchProfCtr. */
 
4308
   if (addProfInc) {
 
4309
      addInstr(env, X86Instr_ProfInc());
 
4310
   }
 
4311
 
4143
4312
   /* Ok, finally we can iterate over the statements. */
4144
4313
   for (i = 0; i < bb->stmts_used; i++)
4145
 
      iselStmt(env,bb->stmts[i]);
 
4314
      iselStmt(env, bb->stmts[i]);
4146
4315
 
4147
 
   iselNext(env,bb->next,bb->jumpkind);
 
4316
   iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
4148
4317
 
4149
4318
   /* record the number of vregs we used. */
4150
4319
   env->code->n_vregs = env->vreg_ctr;