154
154
- The host subarchitecture we are selecting insns for.
155
155
This is set at the start and does not change.
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
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
169
Note, this is all (well, mostly) host-independent.
174
/* Constant -- are set at the start and do not change. */
161
175
IRTypeEnv* type_env;
183
Bool chainingAllowed;
186
/* These are modified as we go along. */
167
187
HInstrArray* code;
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(
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));
3814
3833
/* --------- Indexed PUT --------- */
3815
3834
case Ist_PutI: {
3835
IRPutI *puti = stmt->Ist.PutI.details;
3817
3838
= genGuestArrayOffset(
3818
env, stmt->Ist.PutI.descr,
3819
stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
3840
puti->ix, puti->bias );
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 ));
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 ));
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 ));
3837
3858
if (ty == Ity_I64) {
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 ));
4039
4060
/* --------- EXIT --------- */
4040
4061
case Ist_Exit: {
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));
4063
vpanic("iselStmt(x86): Ist_Exit: dst is not a 32-bit value");
4065
X86CondCode cc = iselCondCode(env, stmt->Ist.Exit.guard);
4066
X86AMode* amEIP = X86AMode_IR(stmt->Ist.Exit.offsIP,
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
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));
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));
4090
/* Case: assisted transfer to arbitrary address */
4091
switch (stmt->Ist.Exit.jk) {
4092
/* Keep this list in sync with that in iselNext below */
4100
case Ijk_Sys_int128:
4101
case Ijk_Sys_int129:
4102
case Ijk_Sys_int130:
4103
case Ijk_Sys_sysenter:
4107
HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
4108
addInstr(env, X86Instr_XAssisted(r, amEIP, cc, stmt->Ist.Exit.jk));
4115
/* Do we ever expect to see any other kind? */
4051
4119
default: break;
4060
4128
/*--- ISEL: Basic block terminators (Nexts) ---*/
4061
4129
/*---------------------------------------------------------*/
4063
static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk )
4131
static void iselNext ( ISelEnv* env,
4132
IRExpr* next, IRJumpKind jk, Int offsIP )
4066
4134
if (vex_traceflags & VEX_TRACE_VCODE) {
4067
vex_printf("\n-- goto {");
4135
vex_printf( "\n-- PUT(%d) = ", offsIP);
4137
vex_printf( "; exit-");
4068
4138
ppIRJumpKind(jk);
4073
ri = iselIntExpr_RI(env, next);
4074
addInstr(env, X86Instr_Goto(jk, Xcc_ALWAYS,ri));
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
4154
= ((Addr64)cdst->Ico.U32) > env->max_ga;
4155
if (0) vex_printf("%s", toFastEP ? "X" : ".");
4156
addInstr(env, X86Instr_XDirect(cdst->Ico.U32,
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,
4171
/* Case: call/return (==boring) transfer to any address */
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));
4179
addInstr(env, X86Instr_XAssisted(r, amEIP, Xcc_ALWAYS,
4188
/* Case: assisted transfer to arbitrary address */
4190
/* Keep this list in sync with that for Ist_Exit above */
4198
case Ijk_Sys_int128:
4199
case Ijk_Sys_int129:
4200
case Ijk_Sys_int130:
4201
case Ijk_Sys_sysenter:
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));
4214
vex_printf( "\n-- PUT(%d) = ", offsIP);
4216
vex_printf( "; exit-");
4219
vassert(0); // are we expecting any other kind?
4082
4227
/* Translate an entire SB to x86 code. */
4084
HInstrArray* iselSB_X86 ( IRSB* bb, VexArch arch_host,
4085
VexArchInfo* archinfo_host,
4086
VexAbiInfo* vbi/*UNUSED*/ )
4229
HInstrArray* iselSB_X86 ( IRSB* bb,
4231
VexArchInfo* archinfo_host,
4232
VexAbiInfo* vbi/*UNUSED*/,
4233
Int offs_Host_EvC_Counter,
4234
Int offs_Host_EvC_FailAddr,
4235
Bool chainingAllowed,
4089
4240
HReg hreg, hregHI;
4091
4242
UInt hwcaps_host = archinfo_host->hwcaps;
4243
X86AMode *amCounter, *amFailAddr;
4093
4245
/* sanity ... */
4094
4246
vassert(arch_host == VexArchX86);
4141
4297
env->vreg_ctr = j;
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));
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. */
4309
addInstr(env, X86Instr_ProfInc());
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]);
4147
iselNext(env,bb->next,bb->jumpkind);
4316
iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
4149
4318
/* record the number of vregs we used. */
4150
4319
env->code->n_vregs = env->vreg_ctr;