예제 #1
0
 public void EmitCommonFpuInstruction(
     BinaryOperator op,
     bool fReversed,
     bool fPopStack)
 {
     EmitCommonFpuInstruction(op, fReversed, fPopStack, null);
 }
예제 #2
0
 /// <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);
 }
예제 #3
0
 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);
 }
예제 #4
0
 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.");
 }
예제 #5
0
        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);
		}
예제 #7
0
 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);
 }
예제 #8
0
 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.");
 }
예제 #9
0
		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());
		}
예제 #10
0
 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());
 }
예제 #11
0
 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));
 }
예제 #12
0
        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");
            }
        }
예제 #13
0
        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());
        }
예제 #14
0
        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));
        }
예제 #15
0
 public void RewriteBinOp(BinaryOperator opr)
 {
     EmitBinOp(opr, instrCur.op1, instrCur.dataWidth, SrcOp(instrCur.op1), SrcOp(instrCur.op2), CopyFlags.ForceBreak|CopyFlags.EmitCc);
 }
예제 #16
0
 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);
 }