📄 toir.c
字号:
/* SIB, no displacement. */ case 0x04: { UChar sib = getIByte(delta); UChar base_r = toUChar(sib & 7); if (base_r == R_EBP) return 6; else return 2; } /* SIB, with 8-bit displacement. */ case 0x0C: return 3; /* SIB, with 32-bit displacement. */ case 0x14: return 6; default: vpanic("lengthAMode"); return 0; /*notreached*/ }}/*------------------------------------------------------------*//*--- Disassembling common idioms ---*//*------------------------------------------------------------*//* Handle binary integer instructions of the form op E, G meaning op reg-or-mem, reg Is passed the a ptr to the modRM byte, the actual operation, 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 %G, tmp OP %E, tmp PUT tmp, %G If E is mem and OP is not reversible, --> (getAddr E) -> tmpa LD (tmpa), tmpa GET %G, tmp2 OP tmpa, tmp2 PUT tmp2, %G If E is mem and OP is reversible --> (getAddr E) -> tmpa LD (tmpa), tmpa OP %G, tmpa PUT tmpa, %G*/staticUInt dis_op2_E_G ( 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 = getUChar(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, 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 if (op8 == Iop_Sub8 && carrying) { helper_SBB( 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(m
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -