📄 toir.c
字号:
/* addSubCarry == True indicates the intended operation is add-with-carry or subtract-with-borrow. */ if (addSubCarry) { vassert(op8 == Iop_Add8 || op8 == Iop_Sub8); vassert(keep); } if (epartIsReg(rm)) { /* Specially handle XOR reg,reg, because that doesn't really depend on reg, and doing the obvious thing potentially generates a spurious value check failure due to the bogus dependency. Ditto SBB reg,reg. */ if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry)) && gregOfRM(rm) == eregOfRM(rm)) { putIReg(size, gregOfRM(rm), mkU(ty,0)); } assign( dst0, getIReg(size,gregOfRM(rm)) ); assign( src, getIReg(size,eregOfRM(rm)) ); if (addSubCarry && op8 == Iop_Add8) { helper_ADC( size, dst1, dst0, src ); putIReg(size, gregOfRM(rm), mkexpr(dst1)); } else if (addSubCarry && op8 == Iop_Sub8) { helper_SBB( size, dst1, dst0, src ); putIReg(size, gregOfRM(rm), mkexpr(dst1)); } else { assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) ); if (isAddSub(op8)) setFlags_DEP1_DEP2(op8, dst0, src, ty); else setFlags_DEP1(op8, dst1, ty); if (keep) putIReg(size, gregOfRM(rm), mkexpr(dst1)); } DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), nameIReg(size,eregOfRM(rm)), nameIReg(size,gregOfRM(rm))); return 1+delta0; } else { /* E refers to memory */ addr = disAMode ( &len, sorb, delta0, dis_buf); assign( dst0, getIReg(size,gregOfRM(rm)) ); assign( src, loadLE(szToITy(size), mkexpr(addr)) ); if (addSubCarry && op8 == Iop_Add8) { helper_ADC( size, dst1, dst0, src ); putIReg(size, gregOfRM(rm), mkexpr(dst1)); } else if (addSubCarry && op8 == Iop_Sub8) { helper_SBB( size, dst1, dst0, src ); putIReg(size, gregOfRM(rm), mkexpr(dst1)); } else { assign( dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) ); if (isAddSub(op8)) setFlags_DEP1_DEP2(op8, dst0, src, ty); else setFlags_DEP1(op8, dst1, ty); if (keep) putIReg(size, gregOfRM(rm), mkexpr(dst1)); } DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), dis_buf,nameIReg(size,gregOfRM(rm))); return len+delta0; }}/* Handle binary integer instructions of the form op G, E meaning op reg, reg-or-mem Is passed the a ptr to the modRM byte, the actual operation, and the data size. Returns the address advanced completely over this instruction. G(src) is reg. E(dst) is reg-or-mem If E is reg, --> GET %E, tmp OP %G, tmp PUT tmp, %E If E is mem, --> (getAddr E) -> tmpa LD (tmpa), tmpv OP %G, tmpv ST tmpv, (tmpa)*/staticUInt dis_op2_G_E ( UChar sorb, Bool addSubCarry, IROp op8, Bool keep, Int size, Int delta0, HChar* t_x86opc ){ HChar dis_buf[50]; Int len; IRType ty = szToITy(size); IRTemp dst1 = newTemp(ty); IRTemp src = newTemp(ty); IRTemp dst0 = newTemp(ty); UChar rm = getIByte(delta0); IRTemp addr = IRTemp_INVALID; /* addSubCarry == True indicates the intended operation is add-with-carry or subtract-with-borrow. */ if (addSubCarry) { vassert(op8 == Iop_Add8 || op8 == Iop_Sub8); vassert(keep); } if (epartIsReg(rm)) { /* Specially handle XOR reg,reg, because that doesn't really depend on reg, and doing the obvious thing potentially generates a spurious value check failure due to the bogus dependency. Ditto SBB reg,reg.*/ if ((op8 == Iop_Xor8 || (op8 == Iop_Sub8 && addSubCarry)) && gregOfRM(rm) == eregOfRM(rm)) { putIReg(size, eregOfRM(rm), mkU(ty,0)); } assign(dst0, getIReg(size,eregOfRM(rm))); assign(src, getIReg(size,gregOfRM(rm))); if (addSubCarry && op8 == Iop_Add8) { helper_ADC( size, dst1, dst0, src ); putIReg(size, eregOfRM(rm), mkexpr(dst1)); } else if (addSubCarry && op8 == Iop_Sub8) { helper_SBB( size, dst1, dst0, src ); putIReg(size, eregOfRM(rm), mkexpr(dst1)); } else { assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src))); if (isAddSub(op8)) setFlags_DEP1_DEP2(op8, dst0, src, ty); else setFlags_DEP1(op8, dst1, ty); if (keep) putIReg(size, eregOfRM(rm), mkexpr(dst1)); } DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), nameIReg(size,gregOfRM(rm)), nameIReg(size,eregOfRM(rm))); return 1+delta0; } /* E refers to memory */ { addr = disAMode ( &len, sorb, delta0, dis_buf); assign(dst0, loadLE(ty,mkexpr(addr))); assign(src, getIReg(size,gregOfRM(rm))); if (addSubCarry && op8 == Iop_Add8) { helper_ADC( size, dst1, dst0, src ); storeLE(mkexpr(addr), mkexpr(dst1)); } else if (addSubCarry && op8 == Iop_Sub8) { helper_SBB( size, dst1, dst0, src ); storeLE(mkexpr(addr), mkexpr(dst1)); } else { assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src))); if (isAddSub(op8)) setFlags_DEP1_DEP2(op8, dst0, src, ty); else setFlags_DEP1(op8, dst1, ty); if (keep) storeLE(mkexpr(addr), mkexpr(dst1)); } DIP("%s%c %s,%s\n", t_x86opc, nameISize(size), nameIReg(size,gregOfRM(rm)), dis_buf); return len+delta0; }}/* Handle move instructions of the form mov E, G meaning mov reg-or-mem, reg Is passed the a ptr to the modRM byte, and the data size. Returns the address advanced completely over this instruction. E(src) is reg-or-mem G(dst) is reg. If E is reg, --> GET %E, tmpv PUT tmpv, %G If E is mem --> (getAddr E) -> tmpa LD (tmpa), tmpb PUT tmpb, %G*/staticUInt dis_mov_E_G ( UChar sorb, Int size, Int delta0 ){ Int len; UChar rm = getIByte(delta0); HChar dis_buf[50]; if (epartIsReg(rm)) { putIReg(size, gregOfRM(rm), getIReg(size, eregOfRM(rm))); DIP("mov%c %s,%s\n", nameISize(size), nameIReg(size,eregOfRM(rm)), nameIReg(size,gregOfRM(rm))); return 1+delta0; } /* E refers to memory */ { IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf ); putIReg(size, gregOfRM(rm), loadLE(szToITy(size), mkexpr(addr))); DIP("mov%c %s,%s\n", nameISize(size), dis_buf,nameIReg(size,gregOfRM(rm))); return delta0+len; }}/* Handle move instructions of the form mov G, E meaning mov reg, reg-or-mem Is passed the a ptr to the modRM byte, and the data size. Returns the address advanced completely over this instruction. G(src) is reg. E(dst) is reg-or-mem If E is reg, --> GET %G, tmp PUT tmp, %E If E is mem, --> (getAddr E) -> tmpa GET %G, tmpv ST tmpv, (tmpa) */staticUInt dis_mov_G_E ( UChar sorb, Int size, Int delta0 ){ Int len; UChar rm = getIByte(delta0); HChar dis_buf[50]; if (epartIsReg(rm)) { putIReg(size, eregOfRM(rm), getIReg(size, gregOfRM(rm))); DIP("mov%c %s,%s\n", nameISize(size), nameIReg(size,gregOfRM(rm)), nameIReg(size,eregOfRM(rm))); return 1+delta0; } /* E refers to memory */ { IRTemp addr = disAMode ( &len, sorb, delta0, dis_buf); storeLE( mkexpr(addr), getIReg(size, gregOfRM(rm)) ); DIP("mov%c %s,%s\n", nameISize(size), nameIReg(size,gregOfRM(rm)), dis_buf); return len+delta0; }}/* op $immediate, AL/AX/EAX. */staticUInt dis_op_imm_A ( Int size, Bool carrying, IROp op8, Bool keep, Int delta, HChar* t_x86opc ){ IRType ty = szToITy(size); IRTemp dst0 = newTemp(ty); IRTemp src = newTemp(ty); IRTemp dst1 = newTemp(ty); UInt lit = getUDisp(size,delta); assign(dst0, getIReg(size,R_EAX)); assign(src, mkU(ty,lit)); if (isAddSub(op8) && !carrying) { assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) ); setFlags_DEP1_DEP2(op8, dst0, src, ty); } else if (isLogic(op8)) { vassert(!carrying); assign(dst1, binop(mkSizedOp(ty,op8), mkexpr(dst0), mkexpr(src)) ); setFlags_DEP1(op8, dst1, ty); } else if (op8 == Iop_Add8 && carrying) { helper_ADC( size, dst1, dst0, src ); } else vpanic("dis_op_imm_A(x86,guest)"); if (keep) putIReg(size, R_EAX, mkexpr(dst1)); DIP("%s%c $0x%x, %s\n", t_x86opc, nameISize(size), lit, nameIReg(size,R_EAX)); return delta+size;}/* Sign- and Zero-extending moves. */staticUInt dis_movx_E_G ( UChar sorb, Int delta, Int szs, Int szd, Bool sign_extend ){ UChar rm = getIByte(delta); if (epartIsReg(rm)) { putIReg(szd, gregOfRM(rm), unop(mkWidenOp(szs,szd,sign_extend), getIReg(szs,eregOfRM(rm)))); DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z', nameISize(szs), nameISize(szd), nameIReg(szs,eregOfRM(rm)), nameIReg(szd,gregOfRM(rm))); return 1+delta; } /* E refers to memory */ { Int len; HChar dis_buf[50]; IRTemp addr = disAMode ( &len, sorb, delta, dis_buf ); putIReg(szd, gregOfRM(rm), unop(mkWidenOp(szs,szd,sign_extend), loadLE(szToITy(szs),mkexpr(addr)))); DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z', nameISize(szs), nameISize(szd), dis_buf, nameIReg(szd,gregOfRM(rm))); return len+delta; }}/* Generate code to divide ArchRegs EDX:EAX / DX:AX / AX by the 32 / 16 / 8 bit quantity in the given IRTemp. */staticvoid codegen_div ( Int sz, IRTemp t, Bool signed_divide ){ IROp op = signed_divide ? Iop_DivModS64to32 : Iop_DivModU64to32; IRTemp src64 = newTemp(Ity_I64); IRTemp dst64 = newTemp(Ity_I64); switch (sz) { case 4: assign( src64, binop(Iop_32HLto64, getIReg(4,R_EDX), getIReg(4,R_EAX)) ); assign( dst64, binop(op, mkexpr(src64), mkexpr(t)) ); putIReg( 4, R_EAX, unop(Iop_64to32,mkexpr(dst64)) ); putIReg( 4, R_EDX, unop(Iop_64HIto32,mkexpr(dst64)) ); break; case 2: { IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64; IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32; assign( src64, unop(widen3264, binop(Iop_16HLto32, getIReg(2,R_EDX), getIReg(2,R_EAX))) ); assign( dst64, binop(op, mkexpr(src64), unop(widen1632,mkexpr(t))) ); putIReg( 2, R_EAX, unop(Iop_32to16,unop(Iop_64to32,mkexpr(dst64))) ); putIReg( 2, R_EDX, unop(Iop_32to16,unop(Iop_64HIto32,mkexpr(dst64))) ); break; } case 1: { IROp widen3264 = signed_divide ? Iop_32Sto64 : Iop_32Uto64; IROp widen1632 = signed_divide ? Iop_16Sto32 : Iop_16Uto32; IROp widen816 = signed_divide ? Iop_8Sto16 : Iop_8Uto16; assign( src64, unop(widen3264, unop(widen1632, getIReg(2,R_EAX))) ); assign( dst64, binop(op, mkexpr(src64), unop(widen1632, unop(widen816, mkexpr(t)))) ); putIReg( 1, R_AL, unop(Iop_16to8, unop(Iop_32to16, unop(Iop_64to32,mkexpr(dst64)))) ); putIReg( 1, R_AH, unop(Iop_16to8, unop(Iop_32to16, unop(Iop_64HIto32,mkexpr(dst64)))) ); break; } default: vpanic("codegen_div(x86)"); }}static UInt dis_Grp1 ( UChar sorb, Int delta, UChar modrm, Int am_sz, Int d_sz, Int sz, UInt d32 ){ Int len; HChar dis_buf[50]; IRType ty = szToITy(sz); IRTemp dst1 = newTemp(ty); IRTemp src = newTemp(ty); IRTemp dst0 = newTemp(ty); IRTemp addr = IRTemp_INVALID; IROp op8 = Iop_INVALID; UInt mask = sz==1 ? 0xFF : (sz==2 ? 0xFFFF : 0xFFFFFFFF); switch (gregOfRM(modrm)) { case 0: op8 = Iop_Add8; break; case 1: op8 = Iop_Or8;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -