📄 isel.c
字号:
} return PPC32RI_Imm(u); } /* default case: calculate into a register and return that */ { HReg r = iselIntExpr_R ( env, e ); return PPC32RI_Reg(r); }}/* --------------------- RH5u --------------------- *//* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an immediate in the range 1 .. 31 inclusive. Used for doing shift amounts. */static PPC32RH* iselIntExpr_RH5u ( ISelEnv* env, IRExpr* e ){ PPC32RH* ri = iselIntExpr_RH5u_wrk(env, e); /* sanity checks ... */ switch (ri->tag) { case Prh_Imm: vassert(ri->Prh.Imm.imm16 >= 1 && ri->Prh.Imm.imm16 <= 31); vassert(!ri->Prh.Imm.syned); return ri; case Prh_Reg: vassert(hregClass(ri->Prh.Reg.reg) == HRcInt32); vassert(hregIsVirtual(ri->Prh.Reg.reg)); return ri; default: vpanic("iselIntExpr_RH5u: unknown ppc32 RI tag"); }}/* DO NOT CALL THIS DIRECTLY ! */static PPC32RH* iselIntExpr_RH5u_wrk ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I8); /* special case: immediate */ if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U8 && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 31) { return PPC32RH_Imm(False/*unsigned*/, e->Iex.Const.con->Ico.U8); } /* default case: calculate into a register and return that */ { HReg r = iselIntExpr_R ( env, e ); return PPC32RH_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 PPC32CondCode 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 PPC32CondCode 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); /* Constant 1:Bit */ if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True) { // Make a compare that will always be true: HReg r_zero = newVRegI(env); addInstr(env, PPC32Instr_LI32(r_zero, 0)); addInstr(env, PPC32Instr_Cmp32(False/*unsigned*/, /*cr*/7, r_zero, PPC32RH_Reg(r_zero))); return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ ); } /* Not1(...) */ if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) { /* Generate code for the arg, and negate the test condition */ PPC32CondCode cond = iselCondCode(env, e->Iex.Unop.arg); cond.test = invertCondTest(cond.test); return cond; } /* --- patterns rooted at: 32to1 --- *///.. /* 32to1(1Uto32(expr1)) -- the casts are pointless, ignore them *///.. 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(expr1)) -- the casts are pointless, ignore them *///.. 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 */ if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_32to1) { HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); HReg tmp = newVRegI(env); /* could do better, probably -- andi. */ addInstr(env, PPC32Instr_Alu32( Palu_AND, tmp, src, PPC32RH_Imm(False,1))); addInstr(env, PPC32Instr_Cmp32( False/*unsigned*/, 7/*cr*/, tmp, PPC32RH_Imm(False,1))); return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ ); } /* --- patterns rooted at: CmpNEZ8 --- */ /* CmpNEZ8(x) */ /* could do better -- andi. */ if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_CmpNEZ8) { HReg r_32 = iselIntExpr_R(env, e->Iex.Unop.arg); HReg r_l = newVRegI(env); addInstr(env, PPC32Instr_Alu32(Palu_AND, r_l, r_32, PPC32RH_Imm(False,0xFF))); addInstr(env, PPC32Instr_Cmp32(False/*unsigned*/, 7/*cr*/, r_l, PPC32RH_Imm(False,0))); return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ ); } /* --- patterns rooted at: CmpNEZ32 --- */ /* CmpNEZ32(x) */ if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_CmpNEZ32) { HReg r1 = iselIntExpr_R(env, e->Iex.Unop.arg); addInstr(env, PPC32Instr_Cmp32(False/*unsigned*/, 7, r1, PPC32RH_Imm(False,0))); return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ ); } /* --- patterns rooted at: Cmp{EQ,NE}{8,16} --- *///.. /* CmpEQ8 / CmpNE8 *///.. if (e->tag == Iex_Binop //.. && (e->Iex.Binop.op == Iop_CmpEQ8//.. || e->Iex.Binop.op == Iop_CmpNE8)) {//.. HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);//.. X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);//.. HReg r = newVRegI(env);//.. addInstr(env, mk_iMOVsd_RR(r1,r));//.. addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));//.. addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(0xFF),r));//.. switch (e->Iex.Binop.op) {//.. case Iop_CmpEQ8: return Xcc_Z;//.. case Iop_CmpNE8: return Xcc_NZ;//.. default: vpanic("iselCondCode(x86): CmpXX8");//.. }//.. }//.. //.. /* CmpEQ16 / CmpNE16 *///.. if (e->tag == Iex_Binop //.. && (e->Iex.Binop.op == Iop_CmpEQ16//.. || e->Iex.Binop.op == Iop_CmpNE16)) {//.. HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);//.. X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);//.. HReg r = newVRegI(env);//.. addInstr(env, mk_iMOVsd_RR(r1,r));//.. addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));//.. addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(0xFFFF),r));//.. switch (e->Iex.Binop.op) {//.. case Iop_CmpEQ16: return Xcc_Z;//.. case Iop_CmpNE16: return Xcc_NZ;//.. default: vpanic("iselCondCode(x86): CmpXX16");//.. }//.. }//.. //.. /* CmpNE32(1Sto32(b), 0) ==> b *///.. {//.. DECLARE_PATTERN(p_CmpNE32_1Sto32);//.. DEFINE_PATTERN(//.. p_CmpNE32_1Sto32,//.. binop(Iop_CmpNE32, unop(Iop_1Sto32,bind(0)), mkU32(0)));//.. if (matchIRExpr(&mi, p_CmpNE32_1Sto32, e)) {//.. return iselCondCode(env, mi.bindee[0]);//.. }//.. } /* Cmp*32*(x,y) */ if (e->tag == Iex_Binop && (e->Iex.Binop.op == Iop_CmpEQ32 || e->Iex.Binop.op == Iop_CmpNE32 || e->Iex.Binop.op == Iop_CmpLT32S || e->Iex.Binop.op == Iop_CmpLT32U || e->Iex.Binop.op == Iop_CmpLE32S || e->Iex.Binop.op == Iop_CmpLE32U)) { HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); Bool syned = False; if (e->Iex.Binop.op == Iop_CmpLT32S || e->Iex.Binop.op == Iop_CmpLE32S) { syned = True; } PPC32RH* ri2 = iselIntExpr_RH(env, syned, e->Iex.Binop.arg2); addInstr(env, PPC32Instr_Cmp32(syned,7,r1,ri2)); switch (e->Iex.Binop.op) { case Iop_CmpEQ32: return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ ); case Iop_CmpNE32: return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );// case Iop_CmpLT32S: return mk_PPCCondCode( Pct_TRUE, Pcf_LT ); case Iop_CmpLT32U: return mk_PPCCondCode( Pct_TRUE, Pcf_7LT );// case Iop_CmpLE32S: return mk_PPCCondCode( Pct_FALSE, Pcf_GT ); case Iop_CmpLE32U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT ); default: vpanic("iselCondCode(ppc32): CmpXX32"); } }//.. /* CmpNE64(1Sto64(b), 0) ==> b *///.. {//.. DECLARE_PATTERN(p_CmpNE64_1Sto64);//.. DEFINE_PATTERN(//.. p_CmpNE64_1Sto64,//.. binop(Iop_CmpNE64, unop(Iop_1Sto64,bind(0)), mkU64(0)));//.. if (matchIRExpr(&mi, p_CmpNE64_1Sto64, e)) {//.. return iselCondCode(env, mi.bindee[0]);//.. }//.. }//.. //.. /* CmpNE64(x, 0) *///.. {//.. DECLARE_PATTERN(p_CmpNE64_x_zero);//.. DEFINE_PATTERN(//.. p_CmpNE64_x_zero,//.. binop(Iop_CmpNE64, bind(0), mkU64(0)) );//.. if (matchIRExpr(&mi, p_CmpNE64_x_zero, e)) {//.. HReg hi, lo;//.. IRExpr* x = mi.bindee[0];//.. HReg tmp = newVRegI(env);//.. iselInt64Expr( &hi, &lo, env, x );//.. addInstr(env, mk_iMOVsd_RR(hi, tmp));//.. addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(lo), tmp));//.. return Xcc_NZ;//.. }//.. }//.. //.. /* CmpNE64 *///.. if (e->tag == Iex_Binop //.. && e->Iex.Binop.op == Iop_CmpNE64) {//.. HReg hi1, hi2, lo1, lo2;//.. HReg tHi = newVRegI(env);//.. HReg tLo = newVRegI(env);//.. iselInt64Expr( &hi1, &lo1, env, e->Iex.Binop.arg1 );//.. iselInt64Expr( &hi2, &lo2, env, e->Iex.Binop.arg2 );//.. addInstr(env, mk_iMOVsd_RR(hi1, tHi));//.. addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(hi2), tHi));//.. addInstr(env, mk_iMOVsd_RR(lo1, tLo));//.. addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(lo2), tLo));//.. addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(tHi), tLo));//.. switch (e->Iex.Binop.op) {//.. case Iop_CmpNE64: return Xcc_NZ;//.. default: vpanic("iselCondCode(x86): CmpXX64");//.. }//.. } /* CmpNEZ64 */ if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_CmpNEZ64) { HReg hi, lo; HReg tmp = newVRegI(env); iselInt64Expr( &hi, &lo, env, e->Iex.Unop.arg ); addInstr(env, mk_iMOVds_RR(tmp, lo)); addInstr(env, PPC32Instr_Alu32(Palu_OR, tmp, tmp, PPC32RH_Reg(hi))); addInstr(env, PPC32Instr_Cmp32(False/*sign*/,7/*cr*/,tmp,PPC32RH_Imm(False,0))); return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ ); } /* var */ if (e->tag == Iex_Tmp) { HReg r_src = lookupIRTemp(env, e->Iex.Tmp.tmp); HReg src_masked = newVRegI(env); addInstr(env, PPC32Instr_Alu32(Palu_AND, src_masked, r_src, PPC32RH_Imm(False,1))); addInstr(env, PPC32Instr_Cmp32(False/*unsigned*/, 7/*cr*/, src_masked, PPC32RH_Imm(False,1))); return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ ); } ppIRExpr(e); vpanic("iselCondCode(ppc32)");}/*---------------------------------------------------------*//*--- ISEL: Integer expressions (64 bit) ---*//*---------------------------------------------------------*//* Compute a 64-bit value into a register pair, which is returned as the first two parameters. As with iselIntExpr_R, these may be either real or virtual regs; in any case they must not be changed by subsequent code emitted by the caller. */static void iselInt64Expr ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ){ iselInt64Expr_wrk(rHi, rLo, env, e);# if 0 vex_printf("\n"); ppIRExpr(e); vex_printf("\n");# endif vassert(hregClass(*rHi) == HRcInt32); vassert(hregIsVirtual(*rHi)); vassert(hregClass(*rLo) == HRcInt32); vassert(hregIsVirtual(*rLo));}/* DO NOT CALL THIS DIRECTLY ! */static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ){// HWord fn = 0; /* helper fn for most SIMD64 stuff */ vassert(e); vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);//.. /* 64-bit literal *///.. if (e->tag == Iex_Const) {//.. ULong w64 = e->Iex.Const.con->Ico.U64;//.. UInt wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;//.. UInt wLo = ((UInt)w64) & 0xFFFFFFFF;//.. HReg tLo = newVRegI(env);//.. HReg tHi = newVRegI(env);//.. vassert(e->Iex.Const.con->tag == Ico_U64);//.. addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wHi), tHi));//.. addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wLo), tLo));//.. *rHi = tHi;//.. *rLo = tLo;//.. return;//.. } /* read 64-bit IRTemp */ if (e->tag == Iex_Tmp) { lookupIRTemp64( rHi, rLo, env, e->Iex.Tmp.tmp); return; }//.. /* 64-bit load *///.. if (e->tag == Iex_LDle) {//.. HReg tLo, tHi;//.. X86AMode *am0, *am4;//.. vassert(e->Iex.LDle.ty == Ity_I64);//.. tLo = newVRegI(env);//.. tHi = newVRegI(env);//.. am0 = iselIntExpr_AMode(env, e->Iex.LDle.addr);//.. am4 = advance4(am0);//.. addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am0), tLo ));//.. addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_M
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -