📄 isel.c
字号:
if (e->Iex.Binop.op == Iop_F64toI32) { /* This works in both mode64 and mode32. */ HReg r1 = StackFramePtr(env->mode64); PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 ); HReg fsrc = iselDblExpr(env, e->Iex.Binop.arg2); HReg ftmp = newVRegF(env); HReg idst = newVRegI(env); /* Set host rounding mode */ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 ); sub_from_sp( env, 16 ); addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/, ftmp, fsrc)); addInstr(env, PPCInstr_FpSTFIW(r1, ftmp)); addInstr(env, PPCInstr_Load(4, idst, zero_r1, mode64)); /* in 64-bit mode we need to sign-widen idst. */ if (mode64) addInstr(env, PPCInstr_Unary(Pun_EXTSW, idst, idst)); add_to_sp( env, 16 ); ///* Restore default FPU rounding. */ //set_FPU_rounding_default( env ); return idst; } if (e->Iex.Binop.op == Iop_F64toI64) { if (mode64) { HReg r1 = StackFramePtr(env->mode64); PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 ); HReg fsrc = iselDblExpr(env, e->Iex.Binop.arg2); HReg idst = newVRegI(env); HReg ftmp = newVRegF(env); /* Set host rounding mode */ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 ); sub_from_sp( env, 16 ); addInstr(env, PPCInstr_FpCftI(False/*F->I*/, False/*int64*/, ftmp, fsrc)); addInstr(env, PPCInstr_FpLdSt(False/*store*/, 8, ftmp, zero_r1)); addInstr(env, PPCInstr_Load(8, idst, zero_r1, True/*mode64*/)); add_to_sp( env, 16 ); ///* Restore default FPU rounding. */ //set_FPU_rounding_default( env ); return idst; } } break; } /* --------- UNARY OP --------- */ case Iex_Unop: { IROp op_unop = e->Iex.Unop.op; /* 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 = iselWordExpr_R(env, expr32); addInstr(env, PPCInstr_Alu(Palu_AND, r_dst, r_src, PPCRH_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); PPCAMode* amode = iselWordExpr_AMode( env, mi.bindee[0] ); addInstr(env, PPCInstr_Load(2,r_dst,amode, mode64)); return r_dst; } } switch (op_unop) { case Iop_8Uto16: case Iop_8Uto32: case Iop_8Uto64: case Iop_16Uto32: case Iop_16Uto64: { HReg r_dst = newVRegI(env); HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg); UShort mask = toUShort(op_unop==Iop_16Uto64 ? 0xFFFF : op_unop==Iop_16Uto32 ? 0xFFFF : 0xFF); addInstr(env, PPCInstr_Alu(Palu_AND,r_dst,r_src, PPCRH_Imm(False,mask))); return r_dst; } case Iop_32Uto64: { HReg r_dst = newVRegI(env); HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg); vassert(mode64); addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/, r_dst, r_src, PPCRH_Imm(False,32))); addInstr(env, PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/, r_dst, r_dst, PPCRH_Imm(False,32))); return r_dst; } case Iop_8Sto16: case Iop_8Sto32: case Iop_16Sto32: { HReg r_dst = newVRegI(env); HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg); UShort amt = toUShort(op_unop==Iop_16Sto32 ? 16 : 24); addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/, r_dst, r_src, PPCRH_Imm(False,amt))); addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/, r_dst, r_dst, PPCRH_Imm(False,amt))); return r_dst; } case Iop_8Sto64: case Iop_16Sto64: case Iop_32Sto64: { HReg r_dst = newVRegI(env); HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg); UShort amt = toUShort(op_unop==Iop_8Sto64 ? 56 : op_unop==Iop_16Sto64 ? 48 : 32); vassert(mode64); addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/, r_dst, r_src, PPCRH_Imm(False,amt))); addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/, r_dst, r_dst, PPCRH_Imm(False,amt))); return r_dst; } case Iop_Not8: case Iop_Not16: case Iop_Not32: case Iop_Not64: { HReg r_dst = newVRegI(env); HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg); addInstr(env, PPCInstr_Unary(Pun_NOT,r_dst,r_src)); return r_dst; } case Iop_64HIto32: { if (!mode64) { HReg rHi, rLo; iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); return rHi; /* and abandon rLo .. poor wee thing :-) */ } else { HReg r_dst = newVRegI(env); HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg); addInstr(env, PPCInstr_Shft(Pshft_SHR, False/*64bit shift*/, r_dst, r_src, PPCRH_Imm(False,32))); return r_dst; } } case Iop_64to32: { if (!mode64) { HReg rHi, rLo; iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); return rLo; /* similar stupid comment to the above ... */ } else { /* This is a no-op. */ return iselWordExpr_R(env, e->Iex.Unop.arg); } } case Iop_64to16: { if (mode64) { /* This is a no-op. */ return iselWordExpr_R(env, e->Iex.Unop.arg); } break; /* evidently not used in 32-bit mode */ } case Iop_16HIto8: case Iop_32HIto16: { HReg r_dst = newVRegI(env); HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg); UShort shift = toUShort(op_unop == Iop_16HIto8 ? 8 : 16); addInstr(env, PPCInstr_Shft(Pshft_SHR, True/*32bit shift*/, r_dst, r_src, PPCRH_Imm(False,shift))); return r_dst; } case Iop_128HIto64: if (mode64) { HReg rHi, rLo; iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg); return rHi; /* and abandon rLo .. poor wee thing :-) */ } break; case Iop_128to64: if (mode64) { HReg rHi, rLo; iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg); return rLo; /* similar stupid comment to the above ... */ } break; case Iop_1Uto32: case Iop_1Uto8: { HReg r_dst = newVRegI(env); PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg); addInstr(env, PPCInstr_Set(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); PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg); addInstr(env, PPCInstr_Set(cond,r_dst)); addInstr(env, PPCInstr_Shft(Pshft_SHL, True/*32bit shift*/, r_dst, r_dst, PPCRH_Imm(False,31))); addInstr(env, PPCInstr_Shft(Pshft_SAR, True/*32bit shift*/, r_dst, r_dst, PPCRH_Imm(False,31))); return r_dst; } case Iop_1Sto64: if (mode64) { /* could do better than this, but for now ... */ HReg r_dst = newVRegI(env); PPCCondCode cond = iselCondCode(env, e->Iex.Unop.arg); addInstr(env, PPCInstr_Set(cond,r_dst)); addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/, r_dst, r_dst, PPCRH_Imm(False,63))); addInstr(env, PPCInstr_Shft(Pshft_SAR, False/*64bit shift*/, r_dst, r_dst, PPCRH_Imm(False,63))); return r_dst; } break; case Iop_Clz32: case Iop_Clz64: { HReg r_src, r_dst; PPCUnaryOp op_clz = (op_unop == Iop_Clz32) ? Pun_CLZ32 : Pun_CLZ64; if (op_unop == Iop_Clz64 && !mode64) goto irreducible; /* Count leading zeroes. */ r_dst = newVRegI(env); r_src = iselWordExpr_R(env, e->Iex.Unop.arg); addInstr(env, PPCInstr_Unary(op_clz,r_dst,r_src)); return r_dst; } case Iop_Neg8: case Iop_Neg16: case Iop_Neg32: case Iop_Neg64: { HReg r_dst = newVRegI(env); HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg); if (op_unop == Iop_Neg64 && !mode64) goto irreducible; addInstr(env, PPCInstr_Unary(Pun_NEG,r_dst,r_src)); return r_dst; } case Iop_V128to32: { HReg r_aligned16; HReg dst = newVRegI(env); HReg vec = iselVecExpr(env, e->Iex.Unop.arg); PPCAMode *am_off0, *am_off12; sub_from_sp( env, 32 ); // Move SP down 32 bytes // get a quadword aligned address within our stack space r_aligned16 = get_sp_aligned16( env ); am_off0 = PPCAMode_IR( 0, r_aligned16 ); am_off12 = PPCAMode_IR( 12,r_aligned16 ); // store vec, load low word to dst addInstr(env, PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 )); addInstr(env, PPCInstr_Load( 4, dst, am_off12, mode64 )); add_to_sp( env, 32 ); // Reset SP return dst; } case Iop_V128to64: case Iop_V128HIto64: if (mode64) { HReg r_aligned16; HReg dst = newVRegI(env); HReg vec = iselVecExpr(env, e->Iex.Unop.arg); PPCAMode *am_off0, *am_off8; sub_from_sp( env, 32 ); // Move SP down 32 bytes // get a quadword aligned address within our stack space r_aligned16 = get_sp_aligned16( env ); am_off0 = PPCAMode_IR( 0, r_aligned16 ); am_off8 = PPCAMode_IR( 8 ,r_aligned16 ); // store vec, load low word (+8) or high (+0) to dst addInstr(env, PPCInstr_AvLdSt( False/*store*/, 16, vec, am_off0 )); addInstr(env, PPCInstr_Load( 8, dst, op_unop == Iop_V128HIto64 ? am_off0 : am_off8, mode64 )); add_to_sp( env, 32 ); // Reset SP return dst; } break; case Iop_16to8: case Iop_32to8: case Iop_32to16: case Iop_64to8: /* These are no-ops. */ if (op_unop == Iop_Neg64 && !mode64) goto irreducible; return iselWordExpr_R(env, e->Iex.Unop.arg); /* ReinterpF64asI64(e) */ /* Given an IEEE754 double, produce an I64 with the same bit pattern. */ case Iop_ReinterpF64asI64: if (mode64) { PPCAMode *am_addr; HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg); HReg r_dst = newVRegI(env); sub_from_sp( env, 16 ); // Move SP down 16 bytes am_addr = PPCAMode_IR( 0, StackFramePtr(mode64) ); // store as F64 addInstr(env, PPCInstr_FpLdSt( False/*store*/, 8, fr_src, am_addr )); // load as Ity_I64 addInstr(env, PPCInstr_Load( 8, r_dst, am_addr, mode64 )); add_to_sp( env, 16 ); // Reset SP return r_dst; } break; default: break; } break; } /* --------- GET --------- */ case Iex_Get: { if (ty == Ity_I8
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -