public void EmitCommonFpuInstruction( BinaryOperator op, bool fReversed, bool fPopStack) { EmitCommonFpuInstruction(op, fReversed, fPopStack, null); }
/// <summary> /// Doesn't handle the x86 idiom add ... adc => long add (and /// sub ..sbc => long sub) /// </summary> /// <param name="i"></param> /// <param name="next"></param> /// <returns></returns> public void RewriteAddSub(BinaryOperator op) { EmitBinOp( op, instrCur.op1, instrCur.op1.Width, SrcOp(instrCur.op1), SrcOp(instrCur.op2), CopyFlags.ForceBreak|CopyFlags.EmitCc); }
public void EmitBinOp(BinaryOperator binOp, MachineOperand dst, DataType dtDst, Expression left, Expression right, CopyFlags flags) { Constant c = right as Constant; if (c != null) { if (c.DataType == PrimitiveType.Byte && left.DataType != c.DataType) { right = emitter.Const(left.DataType, c.ToInt32()); } } //EmitCopy(dst, new BinaryExpression(binOp, dtDst, left, right), true, emitCc); EmitCopy(dst, new BinaryExpression(binOp, dtDst, left, right), flags); }
private void RewriteBranch0(MipsInstruction instr, BinaryOperator condOp, bool link) { if (!link) { var reg = RewriteOperand(instr.op1); var addr = (Address)RewriteOperand(instr.op2); var cond = new BinaryExpression(condOp, PrimitiveType.Bool, reg, Constant.Zero(reg.DataType)); cluster.Class = RtlClass.ConditionalTransfer; emitter.Branch(cond, addr, RtlClass.ConditionalTransfer | RtlClass.Delay); } else throw new NotImplementedException("Linked branches not implemented yet."); }
public void EmitCommonFpuInstruction( BinaryOperator op, bool fReversed, bool fPopStack, DataType cast) { switch (instrCur.Operands) { default: throw new ArgumentOutOfRangeException("di.Instruction", "Instruction must have 1 or 2 operands"); case 1: { // implicit st(0) operand. Identifier opLeft = FpuRegister(0); Expression opRight = SrcOp(instrCur.op1); if (fReversed) { EmitCopy( instrCur.op1, new BinaryExpression(op, instrCur.dataWidth, opRight, MaybeCast(cast, opLeft)), CopyFlags.ForceBreak); } else { emitter.Assign(opLeft, new BinaryExpression(op, instrCur.dataWidth, opLeft, MaybeCast(cast, opRight))); } break; } case 2: { Expression op1 = SrcOp(instrCur.op1); Expression op2 = SrcOp(instrCur.op2); emitter.Assign( SrcOp(instrCur.op1), new BinaryExpression(op, instrCur.op1.Width, fReversed ? op2 : op1, fReversed ? op1 : op2)); break; } } if (fPopStack) { state.ShrinkFpuStack(1); } }
private void BuildCompoundCondition( Block blockFirst, Block blockSecond, BinaryOperator op, bool fInvertFirst, bool fInvertSecond) { Branch brFirst = (Branch) blockFirst.Statements.Last.Instruction; Branch brSecond = (Branch) blockSecond.Statements.Last.Instruction; if (fInvertFirst) { brFirst.Condition = brFirst.Condition.Invert(); } if (fInvertSecond) { brSecond.Condition = brSecond.Condition.Invert(); } brFirst.Condition = new BinaryExpression(op, PrimitiveType.Bool, brFirst.Condition, brSecond.Condition); }
private void RewriteBranch0(MipsInstruction instr, BinaryOperator condOp, bool link) { if (link) { emitter.Assign( frame.EnsureRegister(Registers.ra), instr.Address + 8); } var reg = RewriteOperand(instr.op1); var addr = (Address)RewriteOperand(instr.op2); if (reg is Constant) { // r0 has been replaced with '0'. if (condOp == Operator.Lt) { return; // Branch will never be taken } } var cond = new BinaryExpression(condOp, PrimitiveType.Bool, reg, Constant.Zero(reg.DataType)); cluster.Class = RtlClass.ConditionalTransfer; emitter.Branch(cond, addr, RtlClass.ConditionalTransfer | RtlClass.Delay); }
private void RewriteBranch(MipsInstruction instr, BinaryOperator condOp, bool link) { if (!link) { var reg1 = RewriteOperand(instr.op1); var reg2 = RewriteOperand(instr.op2); var addr = (Address)RewriteOperand(instr.op3); if (condOp == Operator.Eq && ((RegisterOperand)instr.op1).Register == ((RegisterOperand)instr.op2).Register) { cluster.Class = RtlClass.Transfer; emitter.GotoD(addr); } else { var cond = new BinaryExpression(condOp, PrimitiveType.Bool, reg1, reg2); cluster.Class = RtlClass.ConditionalTransfer; emitter.Branch(cond, addr, RtlClass.ConditionalTransfer | RtlClass.Delay); } } else throw new NotImplementedException("Linked branches not implemented yet."); }
private void RunApply(int a, int b, BinaryOperator op, int expected) { Constant c1 = Constant.Word32(a); Constant c2 = Constant.Word32(b); Constant c3 = op.ApplyConstants(c1, c2); Assert.AreEqual(expected, (int) c3.ToInt64()); }
private void RewriteDiv(BinaryOperator op) { Debug.Print(di.dataWidth.ToString()); if (di.dataWidth.BitSize == 16) { di.dataWidth = PrimitiveType.UInt32; var src = orw.RewriteSrc(di.op1, di.Address); var rem = frame.CreateTemporary(PrimitiveType.UInt16); var quot = frame.CreateTemporary(PrimitiveType.UInt16); var regDst = frame.EnsureRegister(((RegisterOperand) di.op2).Register); emitter.Assign(rem, emitter.Cast(rem.DataType, emitter.Remainder(regDst, src))); emitter.Assign(quot, emitter.Cast(quot.DataType, emitter.UDiv(regDst, src))); emitter.Assign(regDst, emitter.Dpb(regDst, rem, 16, 16)); emitter.Assign(regDst, emitter.Dpb(regDst, quot, 0, 16)); emitter.Assign( orw.FlagGroup(FlagM.NF | FlagM.VF | FlagM.ZF), emitter.Cond(quot)); emitter.Assign( orw.FlagGroup(FlagM.CF), Constant.False()); return; } throw new NotImplementedException(di.ToString()); }
public void RewriteAddSubx(BinaryOperator opr) { // We do not take the trouble of widening the CF to the word size // to simplify code analysis in later stages. var x = orw.FlagGroup(FlagM.XF); var src = orw.RewriteSrc(di.op1, di.Address); var dst = orw.RewriteDst(di.op2, di.Address, src, (d, s) => new BinaryExpression( opr, di.dataWidth, new BinaryExpression(opr, di.dataWidth, d, s), x)); emitter.Assign(orw.FlagGroup(FlagM.CVZNX), emitter.Cond(dst)); }
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; case 8: multiplicator = orw.AluRegister(Registers.rax); product = frame.EnsureSequence( orw.AluRegister(Registers.rdx), 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, X86Instruction.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 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), (X86Instruction.DefCc(instrCur.code) & ~FlagM.CF)); emitter.Assign(orw.FlagGroup(FlagM.CF), Constant.False()); }
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; case 8: regQuotient = orw.AluRegister(Registers.rax); regRemainder = orw.AluRegister(Registers.rdx); regDividend = frame.EnsureSequence(regRemainder, regQuotient, PrimitiveType.Word128); 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, X86Instruction.DefCc(instrCur.code)); }
public void RewriteBinOp(BinaryOperator opr) { EmitBinOp(opr, instrCur.op1, instrCur.dataWidth, SrcOp(instrCur.op1), SrcOp(instrCur.op2), CopyFlags.ForceBreak|CopyFlags.EmitCc); }
public void RewriteAdcSbb(BinaryOperator opr) { // We do not take the trouble of widening the CF to the word size // to simplify code analysis in later stages. var c = orw.FlagGroup(FlagM.CF); EmitCopy( instrCur.op1, new BinaryExpression( opr, instrCur.dataWidth, new BinaryExpression( opr, instrCur.dataWidth, SrcOp(instrCur.op1), SrcOp(instrCur.op2)), c), CopyFlags.ForceBreak|CopyFlags.EmitCc); }