public Expression Transform(IntelInstruction instr, MachineOperand op, PrimitiveType opWidth, X86State state) { var reg = op as RegisterOperand; if (reg != null) { return(AluRegister(reg)); } var mem = op as MemoryOperand; if (mem != null) { return(CreateMemoryAccess(instr, mem, opWidth, state)); } var imm = op as ImmediateOperand; if (imm != null) { return(CreateConstant(imm, opWidth)); } var fpu = op as FpuOperand; if (fpu != null) { return(FpuRegister(fpu.StNumber, state)); } var addr = op as AddressOperand; if (addr != null) { return(addr.Address); } throw new NotImplementedException(string.Format("Operand {0}", op)); }
private Expression CreateTestCondition(ConditionCode cc, Opcode opcode) { var grf = orw.FlagGroup(IntelInstruction.UseCc(opcode)); var tc = new TestCondition(cc, grf); return(tc); }
public Expression CreateMemoryAccess(IntelInstruction instr, MemoryOperand mem, DataType dt, X86State state) { var exp = ImportedProcedureName(instr.Address, mem.Width, mem); if (exp != null) { return(new ProcedureConstant(arch.PointerType, exp)); } Expression expr = EffectiveAddressExpression(instr, mem, state); if (IsSegmentedAccessRequired || (mem.DefaultSegment != Registers.ds && mem.DefaultSegment != Registers.ss)) { Expression seg = ReplaceCodeSegment(mem.DefaultSegment, state); if (seg == null) { seg = AluRegister(mem.DefaultSegment); } return(new SegmentedAccess(MemoryIdentifier.GlobalMemory, seg, expr, dt)); } else { return(new MemoryAccess(MemoryIdentifier.GlobalMemory, expr, dt)); } }
/* * the C0 bit becomes the CF (carry) flag, the C2 bit becomes the PF(parity) flag, and the C3 bit becomes the ZF (zero) flag. */ // > 0 // < 1 // = 40 // inordered 45 public FstswChainMatcher(IntelInstruction[] instrs, OperandRewriter orw) { this.instrs = instrs; this.orw = orw; this.zappedInstructions = new Dictionary<int, Opcode>(); this.rewritten = new List<Instruction>(); }
/// <summary> /// A jump to 0xFFFF:0x0000 in real mode is a reboot. /// </summary> /// <param name="instrCur"></param> /// <returns></returns> private bool IsRealModeReboot(IntelInstruction instrCur) { var addrOp = instrCur.op1 as X86AddressOperand; bool isRealModeReboot = addrOp != null && addrOp.Address.ToLinear() == 0xFFFF0; return(isRealModeReboot); }
/// <summary> /// Breaks up very common case of x86: /// <code> /// op [memaddr], reg /// </code> /// into the equivalent: /// <code> /// tmp := [memaddr] op reg; /// store([memaddr], tmp); /// </code> /// </summary> /// <param name="opDst"></param> /// <param name="src"></param> /// <param name="forceBreak">if true, forcibly splits the assignments in two if the destination is a memory store.</param> /// <returns>Returns the destination of the copy.</returns> public void EmitCopy(MachineOperand opDst, Expression src, CopyFlags flags) { Expression dst = SrcOp(opDst); Identifier idDst = dst as Identifier; if (idDst != null || (flags & CopyFlags.ForceBreak) == 0) { emitter.Assign(dst, src); } else { Identifier tmp = frame.CreateTemporary(opDst.Width); emitter.Assign(tmp, src); var ea = orw.CreateMemoryAccess(instrCur, (MemoryOperand)opDst, state); emitter.Assign(ea, tmp); dst = tmp; } if ((flags & CopyFlags.EmitCc) != 0) { EmitCcInstr(dst, IntelInstruction.DefCc(instrCur.code)); } if ((flags & CopyFlags.SetCfIf0) != 0) { emitter.Assign(orw.FlagGroup(FlagM.CF), emitter.Eq0(dst)); } }
/// <summary> /// Implementation of IComparer.Compare. In reality, /// </summary> /// <param name="oInstrA"></param> /// <param name="oInstrB"></param> /// <returns></returns> public int Compare(object oInstrA, object oInstrB) { IntelInstruction instrA = (IntelInstruction)oInstrA; IntelInstruction instrB = (IntelInstruction)oInstrB; if (instrA.code != instrB.code) { return((int)instrB.code - (int)instrA.code); } if (instrA.Operands != instrB.Operands) { return(instrB.Operands - instrA.Operands); } ; int retval = 0; if (instrA.Operands > 0) { retval = CompareOperands(instrA.op1, instrB.op1); if (retval == 0 && instrA.Operands > 1) { retval = CompareOperands(instrA.op2, instrB.op2); if (retval == 0 && instrA.Operands > 2) { retval = CompareOperands(instrA.op3, instrB.op3); } } } return(retval); }
private void RewriteCmp() { Expression op1 = SrcOp(instrCur.op1); Expression op2 = SrcOp(instrCur.op2, instrCur.op1.Width); emitter.Assign( orw.FlagGroup(IntelInstruction.DefCc(Opcode.cmp)), new ConditionOf(emitter.ISub(op1, op2))); }
private void RewriteMultiply(BinaryOperator op, Domain resultDomain) { Expression product; switch (instrCur.Operands) { case 1: Identifier multiplicator; switch (instrCur.op1.Width.Size) { case 1: multiplicator = orw.AluRegister(Registers.al); product = orw.AluRegister(Registers.ax); break; case 2: multiplicator = orw.AluRegister(Registers.ax); product = frame.EnsureSequence( orw.AluRegister(Registers.dx), multiplicator, PrimitiveType.Word32); break; case 4: multiplicator = orw.AluRegister(Registers.eax); product = frame.EnsureSequence( orw.AluRegister(Registers.edx), multiplicator, PrimitiveType.Word64); break; default: throw new ApplicationException(string.Format("Unexpected operand size: {0}", instrCur.op1.Width)); } ; emitter.Assign( product, new BinaryExpression( op, PrimitiveType.Create(resultDomain, product.DataType.Size), SrcOp(instrCur.op1), multiplicator)); EmitCcInstr(product, IntelInstruction.DefCc(instrCur.code)); return; case 2: EmitBinOp(op, instrCur.op1, instrCur.op1.Width.MaskDomain(resultDomain), SrcOp(instrCur.op1), SrcOp(instrCur.op2), CopyFlags.ForceBreak | CopyFlags.EmitCc); return; case 3: EmitBinOp(op, instrCur.op1, instrCur.op1.Width.MaskDomain(resultDomain), SrcOp(instrCur.op2), SrcOp(instrCur.op3), CopyFlags.ForceBreak | CopyFlags.EmitCc); return; default: throw new ArgumentException("Invalid number of operands"); } }
private void RewriteXadd() { var dst = SrcOp(instrCur.op1); var src = SrcOp(instrCur.op2); emitter.Assign( dst, PseudoProc("__xadd", instrCur.op1.Width, dst, src)); EmitCcInstr(dst, IntelInstruction.DefCc(instrCur.code)); }
private void RewriteTest() { var src = new BinaryExpression(Operator.And, instrCur.op1.Width, SrcOp(instrCur.op1), SrcOp(instrCur.op2)); EmitCcInstr(src, (IntelInstruction.DefCc(instrCur.code) & ~FlagM.CF)); emitter.Assign(orw.FlagGroup(FlagM.CF), Constant.False()); }
public void DcffLiveAtEnd() { IntelInstruction [] instrs = new IntelInstruction[] { new IntelInstruction(Opcode.cmp, PrimitiveType.Word32, PrimitiveType.Word32, new RegisterOperand(Registers.eax), new RegisterOperand(Registers.eax)), new IntelInstruction(Opcode.jnz, PrimitiveType.Word32, PrimitiveType.Word32, new ImmediateOperand(Constant.Word32(0x10001010))) }; FlagM [] deadOut = dcff.DeadOutFlags(instrs); Assert.AreEqual(0, (int) deadOut[0]); }
public void Setup() { prog = new Program(); prog.Image = new LoadedImage(Address.Ptr32(0x10000), new byte[4]); var procAddress = Address.Ptr32(0x10000000); instr = new IntelInstruction(Opcode.nop, PrimitiveType.Word32, PrimitiveType.Word32) { Address = procAddress, }; proc = Procedure.Create(procAddress, arch.CreateFrame()); state = (X86State) arch.CreateProcessorState(); orw = new OperandRewriter32(arch, proc.Frame, new FakeRewriterHost(prog)); }
public void DcffConsecutiveAdds() { IntelInstruction [] instrs = new IntelInstruction[] { new IntelInstruction(Opcode.add, PrimitiveType.Word16, PrimitiveType.Word16, new RegisterOperand(Registers.bx), new ImmediateOperand(Constant.Word16(0x10))), new IntelInstruction(Opcode.mov, PrimitiveType.Word16, PrimitiveType.Word16, new RegisterOperand(Registers.si), new RegisterOperand(Registers.bx)), new IntelInstruction(Opcode.add, PrimitiveType.Word16, PrimitiveType.Word16, new RegisterOperand(Registers.cx), new ImmediateOperand(Constant.Word16(1))) }; FlagM [] deadOut = dcff.DeadOutFlags(instrs); Assert.AreEqual(FlagM.SF|FlagM.CF|FlagM.ZF|FlagM.OF, deadOut[0], "Item 0"); Assert.AreEqual(FlagM.SF|FlagM.CF|FlagM.ZF|FlagM.OF, deadOut[1], "Item 1"); Assert.AreEqual(0, (int) deadOut[2], "Item 2"); }
private void RewriteDivide(BinaryOperator op, Domain domain) { if (instrCur.Operands != 1) { throw new ArgumentOutOfRangeException("Intel DIV/IDIV instructions only take one operand"); } Identifier regDividend; Identifier regQuotient; Identifier regRemainder; switch (instrCur.dataWidth.Size) { case 1: regQuotient = orw.AluRegister(Registers.al); regDividend = orw.AluRegister(Registers.ax); regRemainder = orw.AluRegister(Registers.ah); break; case 2: regQuotient = orw.AluRegister(Registers.ax); regRemainder = orw.AluRegister(Registers.dx); regDividend = frame.EnsureSequence(regRemainder, regQuotient, PrimitiveType.Word32); break; case 4: regQuotient = orw.AluRegister(Registers.eax); regRemainder = orw.AluRegister(Registers.edx); regDividend = frame.EnsureSequence(regRemainder, regQuotient, PrimitiveType.Word64); break; default: throw new ArgumentOutOfRangeException(string.Format("{0}-byte divisions not supported.", instrCur.dataWidth.Size)); } ; PrimitiveType p = ((PrimitiveType)regRemainder.DataType).MaskDomain(domain); emitter.Assign( regRemainder, new BinaryExpression(Operator.IMod, p, regDividend, SrcOp(instrCur.op1))); emitter.Assign( regQuotient, new BinaryExpression(op, p, regDividend, SrcOp(instrCur.op1))); EmitCcInstr(regQuotient, IntelInstruction.DefCc(instrCur.code)); }
public void Setup() { arch = new IntelArchitecture(ProcessorMode.Real); var image = new LoadedImage(Address.Ptr32(0x10000), new byte[4]); var prog = new Program( image, image.CreateImageMap(), arch, null); var procAddress = Address.Ptr32(0x10000000); instr = new IntelInstruction(Opcode.nop, PrimitiveType.Word16, PrimitiveType.Word16) { Address = procAddress, }; proc = Procedure.Create(procAddress, arch.CreateFrame()); orw = new OperandRewriter16(arch, proc.Frame, new FakeRewriterHost(prog)); state = (X86State)arch.CreateProcessorState(); }
public Expression Transform(IntelInstruction instr, MachineOperand op, PrimitiveType opWidth, X86State state) { var reg = op as RegisterOperand; if (reg != null) return AluRegister(reg); var mem = op as MemoryOperand; if (mem != null) return CreateMemoryAccess(instr, mem, opWidth, state); var imm = op as ImmediateOperand; if (imm != null) return CreateConstant(imm, opWidth); var fpu = op as FpuOperand; if (fpu != null) return FpuRegister(fpu.StNumber, state); var addr = op as AddressOperand; if (addr != null) return addr.Address; throw new NotImplementedException(string.Format("Operand {0}", op)); }
private int GetHashCodeInner(object obj) { IntelInstruction instr = (IntelInstruction)obj; int hash = instr.code.GetHashCode(); hash = hash * 47 + instr.Operands.GetHashCode(); if (instr.Operands > 0) { hash = hash * 23 + GetHashCode(instr.op1); if (instr.Operands > 1) { hash = hash * 17 + GetHashCode(instr.op2); if (instr.Operands > 2) { hash = hash * 13 + GetHashCode(instr.op3); } } } return(hash); }
private void RewriteLogical(BinaryOperator op) { if (instrCur.code == Opcode.and) { var r = instrCur.op1 as RegisterOperand; if (r != null && r.Register == arch.StackRegister && instrCur.op2 is ImmediateOperand) { emitter.SideEffect(PseudoProc("__align", VoidType.Instance, SrcOp(instrCur.op1))); return; } } EmitBinOp( op, instrCur.op1, instrCur.op1.Width, SrcOp(instrCur.op1), SrcOp(instrCur.op2), CopyFlags.ForceBreak); EmitCcInstr(SrcOp(instrCur.op1), (IntelInstruction.DefCc(instrCur.code) & ~FlagM.CF)); emitter.Assign(orw.FlagGroup(FlagM.CF), Constant.False()); }
private void RewriteStringInstruction() { bool incSi = false; bool incDi = false; var incOperator = GetIncrementOperator(); Identifier regDX; PseudoProcedure ppp; switch (instrCur.code) { default: throw new NotSupportedException(string.Format("'{0}' is not an x86 string instruction.", instrCur.code)); case Opcode.cmps: case Opcode.cmpsb: emitter.Assign( orw.FlagGroup(IntelInstruction.DefCc(Opcode.cmp)), new ConditionOf( new BinaryExpression(Operator.ISub, instrCur.dataWidth, MemSi(), MemDi()))); incSi = true; incDi = true; break; case Opcode.lods: case Opcode.lodsb: emitter.Assign(RegAl, MemSi()); incSi = true; break; case Opcode.movs: case Opcode.movsb: Identifier tmp = frame.CreateTemporary(instrCur.dataWidth); emitter.Assign(tmp, MemSi()); emitter.Assign(MemDi(), tmp); incSi = true; incDi = true; break; case Opcode.ins: case Opcode.insb: regDX = orw.AluRegister(Registers.edx, instrCur.addrWidth); ppp = host.EnsurePseudoProcedure("__in", instrCur.dataWidth, 1); emitter.Assign(MemDi(), emitter.Fn(ppp, regDX)); incDi = true; break; case Opcode.outs: case Opcode.outsb: regDX = orw.AluRegister(Registers.edx, instrCur.addrWidth); ppp = host.EnsurePseudoProcedure("__out" + RegAl.DataType.Prefix, VoidType.Instance, 2); emitter.SideEffect(emitter.Fn(ppp, regDX, RegAl)); incSi = true; break; case Opcode.scas: case Opcode.scasb: emitter.Assign( orw.FlagGroup(IntelInstruction.DefCc(Opcode.cmp)), new ConditionOf( new BinaryExpression(Operator.ISub, instrCur.dataWidth, RegAl, MemDi()))); incDi = true; break; case Opcode.stos: case Opcode.stosb: emitter.Assign(MemDi(), RegAl); incDi = true; break; case Opcode.ret: // "AMD recommends to avoid the penalty by adding rep prefix instead of nop // because it saves decode bandwidth." RewriteRet(); return; } if (incSi) { emitter.Assign(RegSi, new BinaryExpression(incOperator, instrCur.addrWidth, RegSi, Constant.Create(instrCur.addrWidth, instrCur.dataWidth.Size))); } if (incDi) { emitter.Assign(RegDi, new BinaryExpression(incOperator, instrCur.addrWidth, RegDi, Constant.Create(instrCur.addrWidth, instrCur.dataWidth.Size))); } }
public void Execute(IntelInstruction instr) { switch (instr.code) { default: throw new NotImplementedException(string.Format("Instruction emulation for {0} not implemented yet.", instr)); case Opcode.adc: Adc(instr.op1, instr.op2); return; case Opcode.add: Add(instr.op1, instr.op2); return; case Opcode.and: And(instr.op1, instr.op2); return; case Opcode.call: Call(instr.op1); return; case Opcode.cmp: Cmp(instr.op1, instr.op2); return; case Opcode.dec: Dec(instr.op1); return; case Opcode.hlt: running = false; return; case Opcode.inc: Inc(instr.op1); return; case Opcode.ja: if ((Flags & (Cmask | Zmask)) == 0) { InstructionPointer = ((AddressOperand)instr.op1).Address; } return; case Opcode.jbe: if ((Flags & (Cmask | Zmask)) != 0) { InstructionPointer = ((AddressOperand)instr.op1).Address; } return; case Opcode.jc: if ((Flags & Cmask) != 0) { InstructionPointer = ((AddressOperand)instr.op1).Address; } return; case Opcode.jmp: Jump(instr.op1); return; case Opcode.jnc: if ((Flags & Cmask) == 0) { InstructionPointer = ((AddressOperand)instr.op1).Address; } return; case Opcode.jnz: if ((Flags & Zmask) == 0) { InstructionPointer = ((AddressOperand)instr.op1).Address; } return; case Opcode.jz: if ((Flags & Zmask) != 0) { InstructionPointer = ((AddressOperand)instr.op1).Address; } return; case Opcode.lea: Write(instr.op1, GetEffectiveAddress((MemoryOperand)instr.op2)); break; case Opcode.loop: Loop(instr.op1); break; case Opcode.mov: Write(instr.op1, Read(instr.op2)); break; case Opcode.or: Or(instr.op1, instr.op2); return; case Opcode.pop: Write(instr.op1, Pop()); return; case Opcode.popa: Popa(); return; case Opcode.push: Push(Read(instr.op1)); return; case Opcode.pusha: Pusha(); return; case Opcode.repne: Repne(); return; case Opcode.rol: Rol(instr.op1, instr.op2); return; case Opcode.scasb: Scasb(); return; case Opcode.shl: Shl(instr.op1, instr.op2); return; case Opcode.shr: Shr(instr.op1, instr.op2); return; case Opcode.sub: Sub(instr.op1, instr.op2); return; case Opcode.xor: Xor(instr.op1, instr.op2); return; case Opcode.xchg: Xchg(instr.op1, instr.op2); return; } }
/// <summary> /// A jump to 0xFFFF:0x0000 in real mode is a reboot. /// </summary> /// <param name="instrCur"></param> /// <returns></returns> private bool IsRealModeReboot(IntelInstruction instrCur) { var addrOp = instrCur.op1 as X86AddressOperand; bool isRealModeReboot = addrOp != null && addrOp.Address.ToLinear() == 0xFFFF0; return isRealModeReboot; }
private IntelInstruction CreatePush(IntelRegister reg) { IntelInstruction inst = new IntelInstruction( Opcode.push, reg.DataType, reg.DataType, new RegisterOperand(reg)); return inst; }
private IntelInstruction CreateMov(IntelRegister regDst, IntelRegister regSrc) { IntelInstruction inst = new IntelInstruction( Opcode.mov, PrimitiveType.Word16, PrimitiveType.Word16, new RegisterOperand(regDst), new RegisterOperand(regSrc)); return inst; }
/// <summary> /// Iterator that yields one RtlIntructionCluster for each x86 instruction. /// </summary> /// <returns></returns> public IEnumerator <RtlInstructionCluster> GetEnumerator() { while (dasm.MoveNext()) { instrCur = dasm.Current; ric = new RtlInstructionCluster(instrCur.Address, instrCur.Length); emitter = new RtlEmitter(ric.Instructions); orw = arch.ProcessorMode.CreateOperandRewriter(arch, frame, host); switch (instrCur.code) { default: throw new AddressCorrelatedException( instrCur.Address, "Rewriting x86 opcode '{0}' is not supported yet.", instrCur.code); case Opcode.aaa: RewriteAaa(); break; case Opcode.aam: RewriteAam(); break; case Opcode.adc: RewriteAdcSbb(BinaryOperator.IAdd); break; case Opcode.add: RewriteAddSub(BinaryOperator.IAdd); break; case Opcode.and: RewriteLogical(BinaryOperator.And); break; case Opcode.arpl: RewriteArpl(); break; case Opcode.bsr: RewriteBsr(); break; case Opcode.bswap: RewriteBswap(); break; case Opcode.bt: RewriteBt(); break; case Opcode.btr: RewriteBtr(); break; case Opcode.bts: RewriteBts(); break; case Opcode.call: RewriteCall(instrCur.op1, instrCur.op1.Width); break; case Opcode.cbw: RewriteCbw(); break; case Opcode.clc: RewriteSetFlag(FlagM.CF, Constant.False()); break; case Opcode.cld: RewriteSetFlag(FlagM.DF, Constant.False()); break; case Opcode.cli: RewriteCli(); break; case Opcode.cmc: emitter.Assign(orw.FlagGroup(FlagM.CF), emitter.Not(orw.FlagGroup(FlagM.CF))); break; case Opcode.cmova: RewriteConditionalMove(ConditionCode.UGT, instrCur.op1, instrCur.op2); break; case Opcode.cmovbe: RewriteConditionalMove(ConditionCode.ULE, instrCur.op1, instrCur.op2); break; case Opcode.cmovc: RewriteConditionalMove(ConditionCode.ULT, instrCur.op1, instrCur.op2); break; case Opcode.cmovge: RewriteConditionalMove(ConditionCode.GE, instrCur.op1, instrCur.op2); break; case Opcode.cmovg: RewriteConditionalMove(ConditionCode.GT, instrCur.op1, instrCur.op2); break; case Opcode.cmovl: RewriteConditionalMove(ConditionCode.LT, instrCur.op1, instrCur.op2); break; case Opcode.cmovle: RewriteConditionalMove(ConditionCode.LE, instrCur.op1, instrCur.op2); break; case Opcode.cmovnc: RewriteConditionalMove(ConditionCode.UGE, instrCur.op1, instrCur.op2); break; case Opcode.cmovno: RewriteConditionalMove(ConditionCode.NO, instrCur.op1, instrCur.op2); break; case Opcode.cmovns: RewriteConditionalMove(ConditionCode.NS, instrCur.op1, instrCur.op2); break; case Opcode.cmovnz: RewriteConditionalMove(ConditionCode.NE, instrCur.op1, instrCur.op2); break; case Opcode.cmovo: RewriteConditionalMove(ConditionCode.OV, instrCur.op1, instrCur.op2); break; case Opcode.cmovpe: RewriteConditionalMove(ConditionCode.PE, instrCur.op1, instrCur.op2); break; case Opcode.cmovpo: RewriteConditionalMove(ConditionCode.PO, instrCur.op1, instrCur.op2); break; case Opcode.cmovs: RewriteConditionalMove(ConditionCode.SG, instrCur.op1, instrCur.op2); break; case Opcode.cmovz: RewriteConditionalMove(ConditionCode.EQ, instrCur.op1, instrCur.op2); break; case Opcode.cmpxchg: RewriteCmpxchg(); break; case Opcode.cmp: RewriteCmp(); break; case Opcode.cmps: RewriteStringInstruction(); break; case Opcode.cmpsb: RewriteStringInstruction(); break; case Opcode.cpuid: RewriteCpuid(); break; case Opcode.cvttsd2si: RewriteCvttsd2si(); break; case Opcode.cwd: RewriteCwd(); break; case Opcode.daa: EmitDaaDas("__daa"); break; case Opcode.das: EmitDaaDas("__das"); break; case Opcode.dec: RewriteIncDec(-1); break; case Opcode.div: RewriteDivide(Operator.UDiv, Domain.UnsignedInt); break; case Opcode.enter: RewriteEnter(); break; case Opcode.fadd: EmitCommonFpuInstruction(Operator.FAdd, false, false); break; case Opcode.faddp: EmitCommonFpuInstruction(Operator.FAdd, false, true); break; case Opcode.fchs: EmitFchs(); break; case Opcode.fclex: RewriteFclex(); break; case Opcode.fcom: RewriteFcom(0); break; case Opcode.fcomp: RewriteFcom(1); break; case Opcode.fcompp: RewriteFcom(2); break; case Opcode.fcos: RewriteFUnary("cos"); break; case Opcode.fdiv: EmitCommonFpuInstruction(Operator.FDiv, false, false); break; case Opcode.fdivp: EmitCommonFpuInstruction(Operator.FDiv, false, true); break; case Opcode.fiadd: EmitCommonFpuInstruction(Operator.FAdd, false, false, PrimitiveType.Real64); break; case Opcode.fimul: EmitCommonFpuInstruction(Operator.FMul, false, false, PrimitiveType.Real64); break; case Opcode.fisub: EmitCommonFpuInstruction(Operator.FSub, false, false, PrimitiveType.Real64); break; case Opcode.fisubr: EmitCommonFpuInstruction(Operator.FSub, true, false, PrimitiveType.Real64); break; case Opcode.fidiv: EmitCommonFpuInstruction(Operator.FDiv, false, false, PrimitiveType.Real64); break; case Opcode.fdivr: EmitCommonFpuInstruction(Operator.FDiv, true, false); break; case Opcode.fdivrp: EmitCommonFpuInstruction(Operator.FDiv, true, true); break; case Opcode.fild: RewriteFild(); break; case Opcode.fistp: RewriteFistp(); break; case Opcode.fld: RewriteFld(); break; case Opcode.fld1: RewriteFldConst(1.0); break; case Opcode.fldcw: RewriteFldcw(); break; case Opcode.fldln2: RewriteFldConst(Constant.Ln2()); break; case Opcode.fldpi: RewriteFldConst(Constant.Pi()); break; case Opcode.fldz: RewriteFldConst(0.0); break; case Opcode.fmul: EmitCommonFpuInstruction(Operator.FMul, false, false); break; case Opcode.fmulp: EmitCommonFpuInstruction(Operator.FMul, false, true); break; case Opcode.fpatan: RewriteFpatan(); break; case Opcode.frndint: RewriteFUnary("__rndint"); break; case Opcode.fsin: RewriteFUnary("sin"); break; case Opcode.fsincos: RewriteFsincos(); break; case Opcode.fsqrt: RewriteFUnary("sqrt"); break; case Opcode.fst: RewriteFst(false); break; case Opcode.fstcw: RewriterFstcw(); break; case Opcode.fstp: RewriteFst(true); break; case Opcode.fstsw: RewriteFstsw(); break; case Opcode.fsub: EmitCommonFpuInstruction(Operator.ISub, false, false); break; case Opcode.fsubp: EmitCommonFpuInstruction(Operator.ISub, false, true); break; case Opcode.fsubr: EmitCommonFpuInstruction(Operator.ISub, true, false); break; case Opcode.fsubrp: EmitCommonFpuInstruction(Operator.ISub, true, true); break; case Opcode.ftst: RewriteFtst(); break; case Opcode.fucompp: RewriteFcom(2); break; case Opcode.fxam: RewriteFxam(); break; case Opcode.fxch: RewriteExchange(); break; case Opcode.fyl2x: RewriteFyl2x(); break; case Opcode.hlt: RewriteHlt(); break; case Opcode.idiv: RewriteDivide(Operator.SDiv, Domain.SignedInt); break; case Opcode.@in: RewriteIn(); break; case Opcode.imul: RewriteMultiply(Operator.SMul, Domain.SignedInt); break; case Opcode.inc: RewriteIncDec(1); break; case Opcode.insb: RewriteStringInstruction(); break; case Opcode.ins: RewriteStringInstruction(); break; case Opcode.@int: RewriteInt(); break; case Opcode.iret: RewriteIret(); break; case Opcode.jmp: RewriteJmp(); break; case Opcode.ja: RewriteConditionalGoto(ConditionCode.UGT, instrCur.op1); break; case Opcode.jbe: RewriteConditionalGoto(ConditionCode.ULE, instrCur.op1); break; case Opcode.jc: RewriteConditionalGoto(ConditionCode.ULT, instrCur.op1); break; case Opcode.jcxz: RewriteJcxz(); break; case Opcode.jge: RewriteConditionalGoto(ConditionCode.GE, instrCur.op1); break; case Opcode.jg: RewriteConditionalGoto(ConditionCode.GT, instrCur.op1); break; case Opcode.jl: RewriteConditionalGoto(ConditionCode.LT, instrCur.op1); break; case Opcode.jle: RewriteConditionalGoto(ConditionCode.LE, instrCur.op1); break; case Opcode.jnc: RewriteConditionalGoto(ConditionCode.UGE, instrCur.op1); break; case Opcode.jno: RewriteConditionalGoto(ConditionCode.NO, instrCur.op1); break; case Opcode.jns: RewriteConditionalGoto(ConditionCode.NS, instrCur.op1); break; case Opcode.jnz: RewriteConditionalGoto(ConditionCode.NE, instrCur.op1); break; case Opcode.jo: RewriteConditionalGoto(ConditionCode.OV, instrCur.op1); break; case Opcode.jpe: RewriteConditionalGoto(ConditionCode.PE, instrCur.op1); break; case Opcode.jpo: RewriteConditionalGoto(ConditionCode.PO, instrCur.op1); break; case Opcode.js: RewriteConditionalGoto(ConditionCode.SG, instrCur.op1); break; case Opcode.jz: RewriteConditionalGoto(ConditionCode.EQ, instrCur.op1); break; case Opcode.lahf: RewriteLahf(); break; case Opcode.lds: RewriteLxs(Registers.ds); break; case Opcode.lea: RewriteLea(); break; case Opcode.leave: RewriteLeave(); break; case Opcode.les: RewriteLxs(Registers.es); break; case Opcode.lfs: RewriteLxs(Registers.fs); break; case Opcode.lgs: RewriteLxs(Registers.gs); break; case Opcode.@lock: RewriteLock(); break; case Opcode.lods: RewriteStringInstruction(); break; case Opcode.lodsb: RewriteStringInstruction(); break; case Opcode.loop: RewriteLoop(0, ConditionCode.EQ); break; case Opcode.loope: RewriteLoop(FlagM.ZF, ConditionCode.EQ); break; case Opcode.loopne: RewriteLoop(FlagM.ZF, ConditionCode.NE); break; case Opcode.lss: RewriteLxs(Registers.ss); break; case Opcode.mov: RewriteMov(); break; case Opcode.movd: RewriteMovzx(); break; case Opcode.movdqa: RewriteMov(); break; case Opcode.movq: RewriteMov(); break; case Opcode.movs: RewriteStringInstruction(); break; case Opcode.movsb: RewriteStringInstruction(); break; case Opcode.movsx: RewriteMovsx(); break; case Opcode.movzx: RewriteMovzx(); break; case Opcode.mul: RewriteMultiply(Operator.UMul, Domain.UnsignedInt); break; case Opcode.neg: RewriteNeg(); break; case Opcode.nop: continue; case Opcode.not: RewriteNot(); break; case Opcode.or: RewriteLogical(BinaryOperator.Or); break; case Opcode.@out: RewriteOut(); break; case Opcode.@outs: RewriteStringInstruction(); break; case Opcode.@outsb: RewriteStringInstruction(); break; case Opcode.palignr: RewritePalignr(); break; case Opcode.pop: RewritePop(); break; case Opcode.popa: RewritePopa(); break; case Opcode.popf: RewritePopf(); break; case Opcode.pshufd: RewritePshufd(); break; case Opcode.punpcklbw: RewritePunpcklbw(); break; case Opcode.punpcklwd: RewritePunpcklwd(); break; case Opcode.push: RewritePush(); break; case Opcode.pusha: RewritePusha(); break; case Opcode.pushf: RewritePushf(); break; case Opcode.pxor: RewritePxor(); break; case Opcode.rcl: RewriteRotation(PseudoProcedure.RolC, true, true); break; case Opcode.rcr: RewriteRotation(PseudoProcedure.RorC, true, false); break; case Opcode.rol: RewriteRotation(PseudoProcedure.Rol, false, true); break; case Opcode.ror: RewriteRotation(PseudoProcedure.Ror, false, false); break; case Opcode.rdtsc: RewriteRdtsc(); break; case Opcode.rep: RewriteRep(); break; case Opcode.repne: RewriteRep(); break; case Opcode.ret: RewriteRet(); break; case Opcode.retf: RewriteRet(); break; case Opcode.sahf: emitter.Assign(orw.FlagGroup(IntelInstruction.DefCc(instrCur.code)), orw.AluRegister(Registers.ah)); break; case Opcode.sar: RewriteBinOp(Operator.Sar); break; case Opcode.sbb: RewriteAdcSbb(BinaryOperator.ISub); break; case Opcode.scas: RewriteStringInstruction(); break; case Opcode.scasb: RewriteStringInstruction(); break; case Opcode.seta: RewriteSet(ConditionCode.UGT); break; case Opcode.setc: RewriteSet(ConditionCode.ULT); break; case Opcode.setbe: RewriteSet(ConditionCode.ULE); break; case Opcode.setg: RewriteSet(ConditionCode.GT); break; case Opcode.setge: RewriteSet(ConditionCode.GE); break; case Opcode.setl: RewriteSet(ConditionCode.LT); break; case Opcode.setle: RewriteSet(ConditionCode.LE); break; case Opcode.setnc: RewriteSet(ConditionCode.UGE); break; case Opcode.setns: RewriteSet(ConditionCode.NS); break; case Opcode.setnz: RewriteSet(ConditionCode.NE); break; case Opcode.seto: RewriteSet(ConditionCode.OV); break; case Opcode.sets: RewriteSet(ConditionCode.SG); break; case Opcode.setz: RewriteSet(ConditionCode.EQ); break; case Opcode.shl: RewriteBinOp(BinaryOperator.Shl); break; case Opcode.shld: RewriteShxd("__shld"); break; case Opcode.shr: RewriteBinOp(BinaryOperator.Shr); break; case Opcode.shrd: RewriteShxd("__shrd"); break; case Opcode.stc: RewriteSetFlag(FlagM.CF, Constant.True()); break; case Opcode.std: RewriteSetFlag(FlagM.DF, Constant.True()); break; case Opcode.sti: break; //$TODO: case Opcode.stos: RewriteStringInstruction(); break; case Opcode.stosb: RewriteStringInstruction(); break; case Opcode.sub: RewriteAddSub(BinaryOperator.ISub); break; case Opcode.test: RewriteTest(); break; case Opcode.wait: break; // used to slow down FPU. case Opcode.xadd: RewriteXadd(); break; case Opcode.xchg: RewriteExchange(); break; case Opcode.xgetbv: RewriteXgetbv(); break; case Opcode.xlat: RewriteXlat(); break; case Opcode.xor: RewriteLogical(BinaryOperator.Xor); break; } yield return(ric); } }
public Expression CreateMemoryAccess(IntelInstruction instr, MemoryOperand mem, DataType dt, X86State state) { var exp = ImportedProcedure(instr.Address, mem.Width, mem); if (exp != null) return new ProcedureConstant(arch.PointerType, exp); Expression expr = EffectiveAddressExpression(instr, mem, state); if (IsSegmentedAccessRequired || (mem.DefaultSegment != Registers.ds && mem.DefaultSegment != Registers.ss)) { Expression seg = ReplaceCodeSegment(mem.DefaultSegment, state); if (seg == null) seg = AluRegister(mem.DefaultSegment); return new SegmentedAccess(MemoryIdentifier.GlobalMemory, seg, expr, dt); } else { return new MemoryAccess(MemoryIdentifier.GlobalMemory, expr, dt); } }
public void Execute(IntelInstruction instr) { switch (instr.code) { default: throw new NotImplementedException(string.Format("Instruction emulation for {0} not implemented yet.", instr)); case Opcode.adc: Adc(instr.op1, instr.op2); return; case Opcode.add: Add(instr.op1, instr.op2); return; case Opcode.and: And(instr.op1, instr.op2); return; case Opcode.call: Call(instr.op1); return; case Opcode.cmp: Cmp(instr.op1, instr.op2); return; case Opcode.dec: Dec(instr.op1); return; case Opcode.hlt: running = false; return; case Opcode.inc: Inc(instr.op1); return; case Opcode.ja: if ((Flags & (Cmask | Zmask)) == 0) InstructionPointer = ((AddressOperand)instr.op1).Address; return; case Opcode.jbe: if ((Flags & (Cmask | Zmask)) != 0) InstructionPointer = ((AddressOperand)instr.op1).Address; return; case Opcode.jc: if ((Flags & Cmask) != 0) InstructionPointer = ((AddressOperand)instr.op1).Address; return; case Opcode.jmp: Jump(instr.op1); return; case Opcode.jnc: if ((Flags & Cmask) == 0) InstructionPointer = ((AddressOperand)instr.op1).Address; return; case Opcode.jnz: if ((Flags & Zmask) == 0) InstructionPointer = ((AddressOperand)instr.op1).Address; return; case Opcode.jz: if ((Flags & Zmask) != 0) InstructionPointer = ((AddressOperand)instr.op1).Address; return; case Opcode.lea: Write(instr.op1, GetEffectiveAddress((MemoryOperand)instr.op2)); break; case Opcode.loop: Loop(instr.op1); break; case Opcode.mov: Write(instr.op1, Read(instr.op2)); break; case Opcode.or: Or(instr.op1, instr.op2); return; case Opcode.pop: Write(instr.op1, Pop()); return; case Opcode.popa: Popa(); return; case Opcode.push: Push(Read(instr.op1)); return; case Opcode.pusha: Pusha(); return; case Opcode.repne: Repne(); return; case Opcode.rol: Rol(instr.op1, instr.op2); return; case Opcode.scasb: Scasb(); return; case Opcode.shl: Shl(instr.op1, instr.op2); return; case Opcode.shr: Shr(instr.op1, instr.op2); return; case Opcode.sub: Sub(instr.op1, instr.op2); return; case Opcode.xor: Xor(instr.op1, instr.op2); return; case Opcode.xchg: Xchg(instr.op1, instr.op2); return; } }
/// <summary> /// Memory accesses are translated into expressions. /// </summary> /// <param name="mem"></param> /// <param name="state"></param> /// <returns></returns> public Expression EffectiveAddressExpression(IntelInstruction instr, MemoryOperand mem, X86State state) { Expression eIndex = null; Expression eBase = null; Expression expr = null; PrimitiveType type = PrimitiveType.CreateWord(mem.Width.Size); bool ripRelative = false; if (mem.Base != RegisterStorage.None) { if (mem.Base == Registers.rip) { ripRelative = true; } else { eBase = AluRegister(mem.Base); if (expr != null) { expr = new BinaryExpression(Operator.IAdd, eBase.DataType, eBase, expr); } else { expr = eBase; } } } if (mem.Offset.IsValid) { if (ripRelative) { expr = instr.Address + (instr.Length + mem.Offset.ToInt64()); } else if (expr != null) { BinaryOperator op = Operator.IAdd; long l = mem.Offset.ToInt64(); if (l < 0 && l > -0x800) { l = -l; op = Operator.ISub; } DataType dt = (eBase != null) ? eBase.DataType : eIndex.DataType; Constant cOffset = Constant.Create(dt, l); expr = new BinaryExpression(op, dt, expr, cOffset); } else { expr = mem.Offset; } } if (mem.Index != RegisterStorage.None) { eIndex = AluRegister(mem.Index); if (mem.Scale != 0 && mem.Scale != 1) { eIndex = new BinaryExpression( Operator.IMul, eIndex.DataType, eIndex, Constant.Create(mem.Width, mem.Scale)); } expr = new BinaryExpression(Operator.IAdd, expr.DataType, expr, eIndex); } return expr; }
public Expression CreateMemoryAccess(IntelInstruction instr, MemoryOperand memoryOperand, X86State state) { return CreateMemoryAccess(instr, memoryOperand, memoryOperand.Width, state); }
/// <summary> /// Memory accesses are translated into expressions. /// </summary> /// <param name="mem"></param> /// <param name="state"></param> /// <returns></returns> public Expression EffectiveAddressExpression(IntelInstruction instr, MemoryOperand mem, X86State state) { Expression eIndex = null; Expression eBase = null; Expression expr = null; PrimitiveType type = PrimitiveType.CreateWord(mem.Width.Size); bool ripRelative = false; if (mem.Base != RegisterStorage.None) { if (mem.Base == Registers.rip) { ripRelative = true; } else { eBase = AluRegister(mem.Base); if (expr != null) { expr = new BinaryExpression(Operator.IAdd, eBase.DataType, eBase, expr); } else { expr = eBase; } } } if (mem.Offset.IsValid) { if (ripRelative) { expr = instr.Address + (instr.Length + mem.Offset.ToInt64()); } else if (expr != null) { BinaryOperator op = Operator.IAdd; long l = mem.Offset.ToInt64(); if (l < 0 && l > -0x800) { l = -l; op = Operator.ISub; } DataType dt = (eBase != null) ? eBase.DataType : eIndex.DataType; Constant cOffset = Constant.Create(dt, l); expr = new BinaryExpression(op, dt, expr, cOffset); } else { expr = mem.Offset; } } if (mem.Index != RegisterStorage.None) { eIndex = AluRegister(mem.Index); if (mem.Scale != 0 && mem.Scale != 1) { eIndex = new BinaryExpression( Operator.IMul, eIndex.DataType, eIndex, Constant.Create(mem.Width, mem.Scale)); } expr = new BinaryExpression(Operator.IAdd, expr.DataType, expr, eIndex); } return(expr); }
public Expression CreateMemoryAccess(IntelInstruction instr, MemoryOperand memoryOperand, X86State state) { return(CreateMemoryAccess(instr, memoryOperand, memoryOperand.Width, state)); }