📄 isel.c
字号:
addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(X86AMode_IR(e->Iex.Get.offset, hregX86_EBP())), dst)); return dst; } if (ty == Ity_I8 || ty == Ity_I16) { HReg dst = newVRegI(env); addInstr(env, X86Instr_LoadEX( toUChar(ty==Ity_I8 ? 1 : 2), False, X86AMode_IR(e->Iex.Get.offset,hregX86_EBP()), dst)); return dst; } break; } case Iex_GetI: { X86AMode* am = genGuestArrayOffset( env, e->Iex.GetI.descr, e->Iex.GetI.ix, e->Iex.GetI.bias ); HReg dst = newVRegI(env); if (ty == Ity_I8) { addInstr(env, X86Instr_LoadEX( 1, False, am, dst )); return dst; } if (ty == Ity_I32) { addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(am), dst)); return dst; } break; } /* --------- CCALL --------- */ case Iex_CCall: { HReg dst = newVRegI(env); vassert(ty == e->Iex.CCall.retty); /* be very restrictive for now. Only 32/64-bit ints allowed for args, and 32 bits for return type. */ if (e->Iex.CCall.retty != Ity_I32) goto irreducible; /* Marshal args, do the call, clear stack. */ doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args ); addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst)); return dst; } /* --------- LITERAL --------- */ /* 32/16/8-bit literals */ case Iex_Const: { X86RMI* rmi = iselIntExpr_RMI ( env, e ); HReg r = newVRegI(env); addInstr(env, X86Instr_Alu32R(Xalu_MOV, rmi, r)); return r; } /* --------- MULTIPLEX --------- */ case Iex_Mux0X: { if ((ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) { HReg r8; HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX); X86RM* r0 = iselIntExpr_RM(env, e->Iex.Mux0X.expr0); HReg dst = newVRegI(env); addInstr(env, mk_iMOVsd_RR(rX,dst)); r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond); addInstr(env, X86Instr_Test32(0xFF, r8)); addInstr(env, X86Instr_CMov32(Xcc_Z,r0,dst)); return dst; } break; } default: break; } /* switch (e->tag) */ /* We get here if no pattern matched. */ irreducible: ppIRExpr(e); vpanic("iselIntExpr_R: cannot reduce tree");}/*---------------------------------------------------------*//*--- ISEL: Integer expression auxiliaries ---*//*---------------------------------------------------------*//* --------------------- AMODEs --------------------- *//* Return an AMode which computes the value of the specified expression, possibly also adding insns to the code list as a result. The expression may only be a 32-bit one.*/static Bool sane_AMode ( X86AMode* am ){ switch (am->tag) { case Xam_IR: return toBool( hregClass(am->Xam.IR.reg) == HRcInt32 && (hregIsVirtual(am->Xam.IR.reg) || am->Xam.IR.reg == hregX86_EBP()) ); case Xam_IRRS: return toBool( hregClass(am->Xam.IRRS.base) == HRcInt32 && hregIsVirtual(am->Xam.IRRS.base) && hregClass(am->Xam.IRRS.index) == HRcInt32 && hregIsVirtual(am->Xam.IRRS.index) ); default: vpanic("sane_AMode: unknown x86 amode tag"); }}static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e ){ X86AMode* am = iselIntExpr_AMode_wrk(env, e); vassert(sane_AMode(am)); return am;}/* DO NOT CALL THIS DIRECTLY ! */static X86AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32); /* Add32(expr1, Shl32(expr2, imm)) */ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add32 && e->Iex.Binop.arg2->tag == Iex_Binop && e->Iex.Binop.arg2->Iex.Binop.op == Iop_Shl32 && e->Iex.Binop.arg2->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8) { UInt shift = e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U8; if (shift == 1 || shift == 2 || shift == 3) { HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg2->Iex.Binop.arg1 ); return X86AMode_IRRS(0, r1, r2, shift); } } /* Add32(expr,i) */ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add32 && e->Iex.Binop.arg2->tag == Iex_Const && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) { HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); return X86AMode_IR(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32, r1); } /* Doesn't match anything in particular. Generate it into a register and use that. */ { HReg r1 = iselIntExpr_R(env, e); return X86AMode_IR(0, r1); }}/* --------------------- RMIs --------------------- *//* Similarly, calculate an expression into an X86RMI operand. As with iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e ){ X86RMI* rmi = iselIntExpr_RMI_wrk(env, e); /* sanity checks ... */ switch (rmi->tag) { case Xrmi_Imm: return rmi; case Xrmi_Reg: vassert(hregClass(rmi->Xrmi.Reg.reg) == HRcInt32); vassert(hregIsVirtual(rmi->Xrmi.Reg.reg)); return rmi; case Xrmi_Mem: vassert(sane_AMode(rmi->Xrmi.Mem.am)); return rmi; default: vpanic("iselIntExpr_RMI: unknown x86 RMI tag"); }}/* DO NOT CALL THIS DIRECTLY ! */static X86RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8); /* special case: immediate */ if (e->tag == Iex_Const) { UInt u; switch (e->Iex.Const.con->tag) { case Ico_U32: u = e->Iex.Const.con->Ico.U32; break; case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break; case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break; default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)"); } return X86RMI_Imm(u); } /* special case: 32-bit GET */ if (e->tag == Iex_Get && ty == Ity_I32) { return X86RMI_Mem(X86AMode_IR(e->Iex.Get.offset, hregX86_EBP())); } /* special case: 32-bit load from memory */ if (e->tag == Iex_Load && ty == Ity_I32 && e->Iex.Load.end == Iend_LE) { X86AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr); return X86RMI_Mem(am); } /* default case: calculate into a register and return that */ { HReg r = iselIntExpr_R ( env, e ); return X86RMI_Reg(r); }}/* --------------------- RIs --------------------- *//* Calculate an expression into an X86RI operand. As with iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */static X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e ){ X86RI* ri = iselIntExpr_RI_wrk(env, e); /* sanity checks ... */ switch (ri->tag) { case Xri_Imm: return ri; case Xrmi_Reg: vassert(hregClass(ri->Xri.Reg.reg) == HRcInt32); vassert(hregIsVirtual(ri->Xri.Reg.reg)); return ri; default: vpanic("iselIntExpr_RI: unknown x86 RI tag"); }}/* DO NOT CALL THIS DIRECTLY ! */static X86RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8); /* special case: immediate */ if (e->tag == Iex_Const) { UInt u; switch (e->Iex.Const.con->tag) { case Ico_U32: u = e->Iex.Const.con->Ico.U32; break; case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break; case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break; default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)"); } return X86RI_Imm(u); } /* default case: calculate into a register and return that */ { HReg r = iselIntExpr_R ( env, e ); return X86RI_Reg(r); }}/* --------------------- RMs --------------------- *//* Similarly, calculate an expression into an X86RM operand. As with iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */static X86RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e ){ X86RM* rm = iselIntExpr_RM_wrk(env, e); /* sanity checks ... */ switch (rm->tag) { case Xrm_Reg: vassert(hregClass(rm->Xrm.Reg.reg) == HRcInt32); vassert(hregIsVirtual(rm->Xrm.Reg.reg)); return rm; case Xrm_Mem: vassert(sane_AMode(rm->Xrm.Mem.am)); return rm; default: vpanic("iselIntExpr_RM: unknown x86 RM tag"); }}/* DO NOT CALL THIS DIRECTLY ! */static X86RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8); /* special case: 32-bit GET */ if (e->tag == Iex_Get && ty == Ity_I32) { return X86RM_Mem(X86AMode_IR(e->Iex.Get.offset, hregX86_EBP())); } /* special case: load from memory */ /* default case: calculate into a register and return that */ { HReg r = iselIntExpr_R ( env, e ); return X86RM_Reg(r); }}/* --------------------- CONDCODE --------------------- *//* Generate code to evaluated a bit-typed expression, returning the condition code which would correspond when the expression would notionally have returned 1. */static X86CondCode iselCondCode ( ISelEnv* env, IRExpr* e ){ /* Uh, there's nothing we can sanity check here, unfortunately. */ return iselCondCode_wrk(env,e);}/* DO NOT CALL THIS DIRECTLY ! */static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ){ MatchInfo mi; DECLARE_PATTERN(p_32to1); DECLARE_PATTERN(p_1Uto32_then_32to1); DECLARE_PATTERN(p_1Sto32_then_32to1); vassert(e); vassert(typeOfIRExpr(env->type_env,e) == Ity_I1); /* var */ if (e->tag == Iex_Tmp) { HReg r32 = lookupIRTemp(env, e->Iex.Tmp.tmp); /* Test32 doesn't modify r32; so this is OK. */ addInstr(env, X86Instr_Test32(1,r32)); return Xcc_NZ; } /* Constant 1:Bit */ if (e->tag == Iex_Const) { HReg r; vassert(e->Iex.Const.con->tag == Ico_U1); vassert(e->Iex.Const.con->Ico.U1 == True || e->Iex.Const.con->Ico.U1 == False); r = newVRegI(env); addInstr(env, X86Instr_Alu32R(Xalu_MOV,X86RMI_Imm(0),r)); addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(r),r)); return e->Iex.Const.con->Ico.U1 ? Xcc_Z : Xcc_NZ; } /* Not1(e) */ if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) { /* Generate code for the arg, and negate the test condition */ return 1 ^ iselCondCode(env, e->Iex.Unop.arg); } /* --- patterns rooted at: 32to1 --- */ /* 32to1(1Uto32(e)) ==> e */ DEFINE_PATTERN(p_1Uto32_then_32to1, unop(Iop_32to1,unop(Iop_1Uto32,bind(0)))); if (matchIRExpr(&mi,p_1Uto32_then_32to1,e)) { IRExpr* expr1 = mi.bindee[0]; return iselCondCode(env, expr1); } /* 32to1(1Sto32(e)) ==> e */ DEFINE_PATTERN(p_1Sto32_then_32to1, unop(Iop_32to1,unop(Iop_1Sto32,bind(0)))); if (matchIRExpr(&mi,p_1Sto32_then_32to1,e)) { IRExpr* expr1 = mi.bindee[0]; return iselCondCode(env, expr1); } /* 32to1(expr32) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -