📄 isel.c
字号:
//:: addInstr(env, PPC32Instr_MulL(True, 0, r_dst, r_srcL, ri_srcR));//:: return r_dst;//:: }//:: }//:: //:: /* 64to32(MullU32(expr,expr)) *///:: {//:: DECLARE_PATTERN(p_MullU32_then_64to32);//:: DEFINE_PATTERN(p_MullU32_then_64to32,//:: unop(Iop_64to32,//:: binop(Iop_MullU32, bind(0), bind(1))));//:: if (matchIRExpr(&mi,p_MullU32_then_64to32,e)) {//:: HReg r_dst = newVRegI(env);//:: HReg r_srcL = iselIntExpr_R( env, mi.bindee[0] );//:: PPC32RI* ri_srcR = mk_FitRI16_S(env, iselIntExpr_RI( env, mi.bindee[1] ));//:: addInstr(env, PPC32Instr_MulL(False, 0, r_dst, r_srcL, ri_srcR));//:: return r_dst;//:: }//:: }//:: //:: // CAB: Also: 64HIto32(MullU32(expr,expr))//:: // CAB: Also: 64HIto32(MullS32(expr,expr)) HReg rHi, rLo; iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); return rLo; /* similar stupid comment to the above ... */ } case Iop_16HIto8: case Iop_32HIto16: { HReg r_dst = newVRegI(env); HReg r_src = iselIntExpr_R(env, e->Iex.Unop.arg); UInt shift = e->Iex.Unop.op == Iop_16HIto8 ? 8 : 16; addInstr(env, PPC32Instr_Alu32(Palu_SHR, r_dst, r_src, PPC32RH_Imm(False,shift))); return r_dst; } case Iop_1Uto32: case Iop_1Uto8: { HReg r_dst = newVRegI(env); PPC32CondCode cond = iselCondCode(env, e->Iex.Unop.arg); addInstr(env, PPC32Instr_Set32(cond,r_dst)); return r_dst; } case Iop_1Sto8: case Iop_1Sto16: case Iop_1Sto32: { /* could do better than this, but for now ... */ HReg r_dst = newVRegI(env); PPC32CondCode cond = iselCondCode(env, e->Iex.Unop.arg); addInstr(env, PPC32Instr_Set32(cond,r_dst)); addInstr(env, PPC32Instr_Alu32(Palu_SHL, r_dst, r_dst, PPC32RH_Imm(False,31))); addInstr(env, PPC32Instr_Alu32(Palu_SAR, r_dst, r_dst, PPC32RH_Imm(False,31))); return r_dst; }//.. case Iop_Ctz32: {//.. /* Count trailing zeroes, implemented by x86 'bsfl' *///.. HReg dst = newVRegI(env);//.. HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);//.. addInstr(env, X86Instr_Bsfr32(True,src,dst));//.. return dst;//.. } case Iop_Clz32: { /* Count leading zeroes. */ HReg r_dst = newVRegI(env); HReg r_src = iselIntExpr_R(env, e->Iex.Unop.arg); addInstr(env, PPC32Instr_Unary32(Pun_CLZ,r_dst,r_src)); return r_dst; } case Iop_Neg8: case Iop_Neg16: case Iop_Neg32: { HReg r_dst = newVRegI(env); HReg r_src = iselIntExpr_R(env, e->Iex.Unop.arg); addInstr(env, PPC32Instr_Unary32(Pun_NEG,r_dst,r_src)); return r_dst; }//.. case Iop_V128to32: {//.. HReg dst = newVRegI(env);//.. HReg vec = iselVecExpr(env, e->Iex.Unop.arg);//.. X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());//.. sub_from_esp(env, 16);//.. addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, esp0));//.. addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(esp0), dst ));//.. add_to_esp(env, 16);//.. return dst;//.. } case Iop_16to8: case Iop_32to8: case Iop_32to16: /* These are no-ops. */ return iselIntExpr_R(env, e->Iex.Unop.arg); default: break; } break; } /* --------- GET --------- */ case Iex_Get: { if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32) { HReg r_dst = newVRegI(env); PPC32AMode* am_addr = PPC32AMode_IR(e->Iex.Get.offset, GuestStatePtr ); addInstr(env, PPC32Instr_Load( toUChar(sizeofIRType(ty)), False, r_dst, am_addr )); return r_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_Load( 1, False, am, dst ));//.. return dst;//.. }//.. break;//.. } /* --------- CCALL --------- */ case Iex_CCall: { HReg r_dst = newVRegI(env); vassert(ty == Ity_I32); /* 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 ); /* GPR3 now holds the destination address from Pin_Goto */ addInstr(env, mk_iMOVds_RR(r_dst, hregPPC32_GPR3())); return r_dst; } /* --------- LITERAL --------- */ /* 32/16/8-bit literals */ case Iex_Const: { Int i; HReg r_dst = newVRegI(env); switch (e->Iex.Const.con->tag) { case Ico_U32: i = (Int)e->Iex.Const.con->Ico.U32; break; case Ico_U16: i = (Int)(Short)e->Iex.Const.con->Ico.U16; break; case Ico_U8: i = (Int)(Char)e->Iex.Const.con->Ico.U8; break; default: vpanic("iselIntExpr_R.const(ppc32)"); } addInstr(env, PPC32Instr_LI32(r_dst, (UInt)i)); return r_dst; } /* --------- MULTIPLEX --------- */ case Iex_Mux0X: { if ((ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) { PPC32CondCode cc = mk_PPCCondCode( Pct_TRUE, Pcf_7EQ ); HReg r_cond = iselIntExpr_R(env, e->Iex.Mux0X.cond); HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX); PPC32RI* r0 = iselIntExpr_RI(env, e->Iex.Mux0X.expr0); HReg r_dst = newVRegI(env); HReg r_tmp = newVRegI(env); addInstr(env, mk_iMOVds_RR(r_dst,rX)); addInstr(env, PPC32Instr_Alu32(Palu_AND, r_tmp, r_cond, PPC32RH_Imm(False,0xFF))); addInstr(env, PPC32Instr_Cmp32(False/*unsigned*/, 7/*cr*/, r_tmp, PPC32RH_Imm(False,0))); addInstr(env, PPC32Instr_CMov32(cc,r_dst,r0)); return r_dst; } break; } default: break; } /* switch (e->tag) */ /* We get here if no pattern matched. */ irreducible: ppIRExpr(e); vpanic("iselIntExpr_R(ppc32): 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 fits16bits ( UInt u ) { /* Is u the same as the sign-extend of its lower 16 bits? */ Int i = u & 0xFFFF; i <<= 16; i >>= 16; return toBool(u == (UInt)i);}static Bool sane_AMode ( PPC32AMode* am ){ switch (am->tag) { case Pam_IR: return toBool( hregClass(am->Pam.IR.base) == HRcInt32 && hregIsVirtual(am->Pam.IR.base) && fits16bits(am->Pam.IR.index) ); case Pam_RR: return toBool( hregClass(am->Pam.RR.base) == HRcInt32 && hregIsVirtual(am->Pam.IR.base) && hregClass(am->Pam.RR.base) == HRcInt32 && hregIsVirtual(am->Pam.IR.base) ); default: vpanic("sane_AMode: unknown ppc32 amode tag"); }}static PPC32AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e ){ PPC32AMode* am = iselIntExpr_AMode_wrk(env, e); vassert(sane_AMode(am)); return am;}/* DO NOT CALL THIS DIRECTLY ! */static PPC32AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32); /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */ 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 && fits16bits(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32)) { return PPC32AMode_IR(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32, iselIntExpr_R(env, e->Iex.Binop.arg1)); } /* Add32(expr,expr) */ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add32) { HReg r_base = iselIntExpr_R(env, e->Iex.Binop.arg1); HReg r_idx = iselIntExpr_R(env, e->Iex.Binop.arg2); return PPC32AMode_RR(r_idx, r_base); } /* Doesn't match anything in particular. Generate it into a register and use that. */ { HReg r1 = iselIntExpr_R(env, e); return PPC32AMode_IR(0, r1); }}/* --------------------- RH --------------------- *//* Compute an I8/I16/I32 into a RH (reg-or-halfword-immediate). It's important to specify whether the immediate is to be regarded as signed or not. If yes, this will never return -32768 as an immediate; this guaranteed that all signed immediates that are return can have their sign inverted if need be. */static PPC32RH* iselIntExpr_RH ( ISelEnv* env, Bool syned, IRExpr* e ){ PPC32RH* ri = iselIntExpr_RH_wrk(env, syned, e); /* sanity checks ... */ switch (ri->tag) { case Prh_Imm: vassert(ri->Prh.Imm.syned == syned); if (syned) vassert(ri->Prh.Imm.imm16 != 0x8000); return ri; case Prh_Reg: vassert(hregClass(ri->Prh.Reg.reg) == HRcInt32); vassert(hregIsVirtual(ri->Prh.Reg.reg)); return ri; default: vpanic("iselIntExpr_RH: unknown ppc32 RH tag"); }}/* DO NOT CALL THIS DIRECTLY ! */static PPC32RH* iselIntExpr_RH_wrk ( ISelEnv* env, Bool syned, IRExpr* e ){ UInt u; Int i; IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32); /* special case: immediate */ if (e->tag == Iex_Const) { /* What value are we aiming to generate? */ 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_RH.Iex_Const(ppc32h)"); } i = (Int)u; /* Now figure out if it's representable. */ if (!syned && u <= 65535) { return PPC32RH_Imm(False/*unsigned*/, u & 0xFFFF); } if (syned && i >= -32767 && i <= 32767) { return PPC32RH_Imm(True/*signed*/, u & 0xFFFF); } /* no luck; use the Slow Way. */ } /* default case: calculate into a register and return that */ { HReg r = iselIntExpr_R ( env, e ); return PPC32RH_Reg(r); }}/* --------------------- RIs --------------------- *//* Calculate an expression into an PPC32RI operand. As with iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */static PPC32RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e ){ PPC32RI* ri = iselIntExpr_RI_wrk(env, e); /* sanity checks ... */ switch (ri->tag) { case Pri_Imm: return ri; case Pri_Reg: vassert(hregClass(ri->Pri.Reg) == HRcInt32); vassert(hregIsVirtual(ri->Pri.Reg)); return ri; default: vpanic("iselIntExpr_RI: unknown ppc32 RI tag"); }}/* DO NOT CALL THIS DIRECTLY ! */static PPC32RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32); /* 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; default: vpanic("iselIntExpr_RI.Iex_Const(ppc32h)");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -