📄 isel.c
字号:
want to modify it, ask for a new vreg, copy it in there, and modify the copy. The register allocator will do its best to map both vregs to the same real register, so the copies will often disappear later in the game. This should handle expressions of 32, 16 and 8-bit type. All results are returned in a 32-bit register. For 16- and 8-bit expressions, the upper 16/24 bits are arbitrary, so you should mask or sign extend partial values if necessary.*/static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ){ HReg r = iselIntExpr_R_wrk(env, e); /* sanity checks ... */# if 0 vex_printf("\n"); ppIRExpr(e); vex_printf("\n");# endif vassert(hregClass(r) == HRcInt32); vassert(hregIsVirtual(r)); return r;}/* DO NOT CALL THIS DIRECTLY ! */static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ){ MatchInfo mi; DECLARE_PATTERN(p_32to1_then_1Uto8); IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32 || Ity_I16 || Ity_I8); switch (e->tag) { /* --------- TEMP --------- */ case Iex_Tmp: return lookupIRTemp(env, e->Iex.Tmp.tmp); /* --------- LOAD --------- */ case Iex_Load: { HReg r_dst = newVRegI(env); PPC32AMode* am_addr = iselIntExpr_AMode(env, e->Iex.Load.addr); if (e->Iex.Load.end != Iend_BE) goto irreducible; if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32) { addInstr(env, PPC32Instr_Load( toUChar(sizeofIRType(ty)), False, r_dst, am_addr )); return r_dst; } break; } /* --------- BINARY OP --------- */ case Iex_Binop: { PPC32AluOp aluOp;//.. /* Pattern: Sub32(0,x) *///.. if (e->Iex.Binop.op == Iop_Sub32 && isZero32(e->Iex.Binop.arg1)) {//.. HReg dst = newVRegI(env);//.. HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2);//.. addInstr(env, mk_iMOVsd_RR(reg,dst));//.. addInstr(env, PPC32Instr_Unary32(Xun_NEG,PPC32RM_Reg(dst)));//.. return dst;//.. } /* Is it an addition or logical style op? */ switch (e->Iex.Binop.op) { case Iop_Add8: case Iop_Add16: case Iop_Add32: aluOp = Palu_ADD; break; case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: aluOp = Palu_SUB; break; case Iop_And8: case Iop_And16: case Iop_And32: aluOp = Palu_AND; break; case Iop_Or8: case Iop_Or16: case Iop_Or32: aluOp = Palu_OR; break; case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: aluOp = Palu_XOR; break; case Iop_Shl32: case Iop_Shl16: case Iop_Shl8: aluOp = Palu_SHL; break; case Iop_Shr32: case Iop_Shr16: case Iop_Shr8: aluOp = Palu_SHR; break; case Iop_Sar32: case Iop_Sar16: case Iop_Sar8: aluOp = Palu_SAR; break; default: aluOp = Palu_INVALID; break; } /* For commutative ops we assume any literal values are on the second operand. */ if (aluOp != Palu_INVALID) { HReg r_dst, r_srcL; PPC32RH* ri_srcR = NULL; r_dst = newVRegI(env); /* get left arg into a reg */ r_srcL = iselIntExpr_R(env, e->Iex.Binop.arg1); /* get right arg into an RH, in the appropriate way */ switch (aluOp) { case Palu_ADD: case Palu_SUB: ri_srcR = iselIntExpr_RH(env, True/*signed*/, e->Iex.Binop.arg2); break; case Palu_AND: case Palu_OR: case Palu_XOR: ri_srcR = iselIntExpr_RH(env, False/*signed*/, e->Iex.Binop.arg2); break; case Palu_SHL: case Palu_SHR: case Palu_SAR: ri_srcR = iselIntExpr_RH5u(env, e->Iex.Binop.arg2); break; default: vpanic("iselIntExpr_R_wrk-aluOp-arg2"); } /* widen the left arg if needed */ if ((aluOp == Palu_SHR || aluOp == Palu_SAR) && (ty == Ity_I8 || ty == Ity_I16)) { PPC32RH* amt = PPC32RH_Imm(False, ty == Ity_I8 ? 24 : 16); HReg tmp = newVRegI(env); addInstr(env, PPC32Instr_Alu32(Palu_SHL, tmp, r_srcL, amt)); addInstr(env, PPC32Instr_Alu32(aluOp, tmp, tmp, amt)); r_srcL = tmp; vassert(0); /* AWAITING TEST CASE */ } addInstr(env, PPC32Instr_Alu32(aluOp, r_dst, r_srcL, ri_srcR)); return r_dst; } /* How about a div? */ if (e->Iex.Binop.op == Iop_DivS32 || e->Iex.Binop.op == Iop_DivU32) { HReg r_dst = newVRegI(env); HReg r_srcL = iselIntExpr_R(env, e->Iex.Binop.arg1); HReg r_srcR = iselIntExpr_R(env, e->Iex.Binop.arg2); addInstr(env, PPC32Instr_Div(toBool(e->Iex.Binop.op == Iop_DivS32), r_dst, r_srcL, r_srcR)); return r_dst; } /* No? Anyone for a mul? */ if (e->Iex.Binop.op == Iop_Mul16 || e->Iex.Binop.op == Iop_Mul32) { Bool syned = True; HReg r_dst = newVRegI(env); HReg r_srcL = iselIntExpr_R(env, e->Iex.Binop.arg1); HReg r_srcR = iselIntExpr_R(env, e->Iex.Binop.arg2); addInstr(env, PPC32Instr_MulL(syned, False/*lo32*/, r_dst, r_srcL, r_srcR)); return r_dst; } /* El-mutanto 3-way compare? */ if (e->Iex.Binop.op == Iop_CmpORD32S || e->Iex.Binop.op == Iop_CmpORD32U) { Bool syned = e->Iex.Binop.op == Iop_CmpORD32S; HReg dst = newVRegI(env); HReg srcL = iselIntExpr_R(env, e->Iex.Binop.arg1); PPC32RH* srcR = iselIntExpr_RH(env, syned, e->Iex.Binop.arg2); addInstr(env, PPC32Instr_Cmp32(syned, /*cr*/7, srcL, srcR)); addInstr(env, PPC32Instr_MfCR(dst)); addInstr(env, PPC32Instr_Alu32(Palu_AND, dst, dst, PPC32RH_Imm(False,7<<1))); return dst; }//zz /* Handle misc other ops. *///zz if (e->Iex.Binop.op == Iop_8HLto16) {//zz HReg hi8 = newVRegI(env);//zz HReg lo8 = newVRegI(env);//zz HReg hi8s = iselIntExpr_R(env, e->Iex.Binop.arg1);//zz HReg lo8s = iselIntExpr_R(env, e->Iex.Binop.arg2);//zz addInstr(env, //zz PPC32Instr_Alu32(Palu_SHL, hi8, hi8s, PPC32RH_Imm(False,8)));//zz addInstr(env, //zz PPC32Instr_Alu32(Palu_AND, lo8, lo8s, PPC32RH_Imm(False,0xFF)));//zz addInstr(env, //zz PPC32Instr_Alu32(Palu_OR, hi8, hi8, PPC32RI_Reg(lo8)));//zz return hi8;//zz }//zz //zz if (e->Iex.Binop.op == Iop_16HLto32) {//zz HReg hi16 = newVRegI(env);//zz HReg lo16 = newVRegI(env);//zz HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1);//zz HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2);//zz addInstr(env, mk_sh32(env, Psh_SHL, hi16, hi16s, PPC32RI_Imm(16)));//zz addInstr(env, PPC32Instr_Alu32(Palu_AND, lo16, lo16s, PPC32RI_Imm(0xFFFF)));//zz addInstr(env, PPC32Instr_Alu32(Palu_OR, hi16, hi16, PPC32RI_Reg(lo16)));//zz return hi16;//zz }//.. if (e->Iex.Binop.op == Iop_MullS16 || e->Iex.Binop.op == Iop_MullS8//.. || e->Iex.Binop.op == Iop_MullU16 || e->Iex.Binop.op == Iop_MullU8) {//.. HReg a16 = newVRegI(env);//.. HReg b16 = newVRegI(env);//.. HReg a16s = iselIntExpr_R(env, e->Iex.Binop.arg1);//.. HReg b16s = iselIntExpr_R(env, e->Iex.Binop.arg2);//.. Int shift = (e->Iex.Binop.op == Iop_MullS8 //.. || e->Iex.Binop.op == Iop_MullU8)//.. ? 24 : 16;//.. X86ShiftOp shr_op = (e->Iex.Binop.op == Iop_MullS8 //.. || e->Iex.Binop.op == Iop_MullS16)//.. ? Xsh_SAR : Xsh_SHR;//.. //.. addInstr(env, mk_iMOVsd_RR(a16s, a16));//.. addInstr(env, mk_iMOVsd_RR(b16s, b16));//.. addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, X86RM_Reg(a16)));//.. addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, X86RM_Reg(b16)));//.. addInstr(env, X86Instr_Sh32(shr_op, shift, X86RM_Reg(a16)));//.. addInstr(env, X86Instr_Sh32(shr_op, shift, X86RM_Reg(b16)));//.. addInstr(env, X86Instr_Alu32R(Xalu_MUL, X86RMI_Reg(a16), b16));//.. return b16;//.. } if (e->Iex.Binop.op == Iop_CmpF64) { HReg fr_srcL = iselDblExpr(env, e->Iex.Binop.arg1); HReg fr_srcR = iselDblExpr(env, e->Iex.Binop.arg2); HReg r_ccPPC32 = newVRegI(env); HReg r_ccIR = newVRegI(env); HReg r_ccIR_b0 = newVRegI(env); HReg r_ccIR_b2 = newVRegI(env); HReg r_ccIR_b6 = newVRegI(env); addInstr(env, PPC32Instr_FpCmp(r_ccPPC32, fr_srcL, fr_srcR)); /* Map compare result from PPC32 to IR, conforming to CmpF64 definition. */ /* FP cmp result | PPC | IR -------------------------- UN | 0x1 | 0x45 EQ | 0x2 | 0x40 GT | 0x4 | 0x00 LT | 0x8 | 0x01 */ // r_ccIR_b0 = r_ccPPC32[0] | r_ccPPC32[3] addInstr(env, PPC32Instr_Alu32(Palu_SHR, r_ccIR_b0, r_ccPPC32, PPC32RH_Imm(False,0x3))); addInstr(env, PPC32Instr_Alu32(Palu_OR, r_ccIR_b0, r_ccPPC32, PPC32RH_Reg(r_ccIR_b0))); addInstr(env, PPC32Instr_Alu32(Palu_AND, r_ccIR_b0, r_ccIR_b0, PPC32RH_Imm(False,0x1))); // r_ccIR_b2 = r_ccPPC32[0] addInstr(env, PPC32Instr_Alu32(Palu_SHL, r_ccIR_b2, r_ccPPC32, PPC32RH_Imm(False,0x2))); addInstr(env, PPC32Instr_Alu32(Palu_AND, r_ccIR_b2, r_ccIR_b2, PPC32RH_Imm(False,0x4))); // r_ccIR_b6 = r_ccPPC32[0] | r_ccPPC32[1] addInstr(env, PPC32Instr_Alu32(Palu_SHR, r_ccIR_b6, r_ccPPC32, PPC32RH_Imm(False,0x1))); addInstr(env, PPC32Instr_Alu32(Palu_OR, r_ccIR_b6, r_ccPPC32, PPC32RH_Reg(r_ccIR_b6))); addInstr(env, PPC32Instr_Alu32(Palu_SHL, r_ccIR_b6, r_ccIR_b6, PPC32RH_Imm(False,0x6))); addInstr(env, PPC32Instr_Alu32(Palu_AND, r_ccIR_b6, r_ccIR_b6, PPC32RH_Imm(False,0x40))); // r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6 addInstr(env, PPC32Instr_Alu32(Palu_OR, r_ccIR, r_ccIR_b0, PPC32RH_Reg(r_ccIR_b2))); addInstr(env, PPC32Instr_Alu32(Palu_OR, r_ccIR, r_ccIR, PPC32RH_Reg(r_ccIR_b6))); return r_ccIR; } if (e->Iex.Binop.op == Iop_F64toI32) { HReg fr_src = iselDblExpr(env, e->Iex.Binop.arg2); HReg r_dst = newVRegI(env); /* Set host rounding mode */ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 ); sub_from_sp( env, 16 ); addInstr(env, PPC32Instr_FpF64toI32(r_dst, fr_src)); add_to_sp( env, 16 ); /* Restore default FPU rounding. */ set_FPU_rounding_default( env ); return r_dst; }//.. /* C3210 flags following FPU partial remainder (fprem), both//.. IEEE compliant (PREM1) and non-IEEE compliant (PREM). *///.. if (e->Iex.Binop.op == Iop_PRemC3210F64//.. || e->Iex.Binop.op == Iop_PRem1C3210F64) {//.. HReg junk = newVRegF(env);//.. HReg dst = newVRegI(env);//.. HReg srcL = iselDblExpr(env, e->Iex.Binop.arg1);//.. HReg srcR = iselDblExpr(env, e->Iex.Binop.arg2);//.. addInstr(env, X86Instr_FpBinary(//.. e->Iex.Binop.op==Iop_PRemC3210F64 //.. ? Xfp_PREM : Xfp_PREM1,//.. srcL,srcR,junk//.. ));//.. /* The previous pseudo-insn will have left the FPU's C3210//.. flags set correctly. So bag them. *///.. addInstr(env, X86Instr_FpStSW_AX());//.. addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst));//.. addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst));//.. return dst;//.. } break; } /* --------- UNARY OP --------- */ case Iex_Unop: { /* 1Uto8(32to1(expr32)) */ DEFINE_PATTERN(p_32to1_then_1Uto8, unop(Iop_1Uto8,unop(Iop_32to1,bind(0)))); if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) { IRExpr* expr32 = mi.bindee[0]; HReg r_dst = newVRegI(env); HReg r_src = iselIntExpr_R(env, expr32); addInstr(env, PPC32Instr_Alu32(Palu_AND, r_dst, r_src, PPC32RH_Imm(False,1))); return r_dst; } /* 16Uto32(LDbe:I16(expr32)) */ { DECLARE_PATTERN(p_LDbe16_then_16Uto32); DEFINE_PATTERN(p_LDbe16_then_16Uto32, unop(Iop_16Uto32, IRExpr_Load(Iend_BE,Ity_I16,bind(0))) ); if (matchIRExpr(&mi,p_LDbe16_then_16Uto32,e)) { HReg r_dst = newVRegI(env); PPC32AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] ); addInstr(env, PPC32Instr_Load(2,False,r_dst,amode)); return r_dst; } } switch (e->Iex.Unop.op) { case Iop_8Uto16: case Iop_8Uto32: case Iop_16Uto32: { HReg r_dst = newVRegI(env); HReg r_src = iselIntExpr_R(env, e->Iex.Unop.arg); UInt mask = e->Iex.Unop.op==Iop_16Uto32 ? 0xFFFF : 0xFF; addInstr(env, PPC32Instr_Alu32(Palu_AND,r_dst,r_src,PPC32RH_Imm(False,mask))); return r_dst; } case Iop_8Sto16: case Iop_8Sto32: case Iop_16Sto32: { HReg r_dst = newVRegI(env); HReg r_src = iselIntExpr_R(env, e->Iex.Unop.arg); UInt amt = e->Iex.Unop.op==Iop_16Sto32 ? 16 : 24; addInstr(env, PPC32Instr_Alu32(Palu_SHL, r_dst, r_src, PPC32RH_Imm(False,amt))); addInstr(env, PPC32Instr_Alu32(Palu_SAR, r_dst, r_dst, PPC32RH_Imm(False,amt))); return r_dst; } case Iop_Not8: case Iop_Not16: case Iop_Not32: { HReg r_dst = newVRegI(env); HReg r_src = iselIntExpr_R(env, e->Iex.Unop.arg); addInstr(env, PPC32Instr_Unary32(Pun_NOT,r_dst,r_src)); return r_dst; } case Iop_64HIto32: { HReg rHi, rLo; iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); return rHi; /* and abandon rLo .. poor wee thing :-) */ } case Iop_64to32: {//:: /* 64to32(MullS32(expr,expr)) *///:: {//:: DECLARE_PATTERN(p_MullS32_then_64to32);//:: DEFINE_PATTERN(p_MullS32_then_64to32,//:: unop(Iop_64to32,//:: binop(Iop_MullS32, bind(0), bind(1))));//:: if (matchIRExpr(&mi,p_MullS32_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] ));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -