public override void Transform(Context context, TransformContext transformContext)
        {
            var result   = context.Result;
            var operand1 = context.Operand1;
            var operand2 = context.Operand2;

            transformContext.SplitLongOperand(result, out Operand resultLow, out Operand resultHigh);

            var branch         = context.ConditionCode;
            var branchUnsigned = context.ConditionCode.GetUnsigned();

            var nextBlock = transformContext.Split(context);
            var newBlocks = transformContext.CreateNewBlockContexts(5, context.Label);

            TransformContext.UpdatePHIInstructionTargets(nextBlock.Block.NextBlocks, context.Block, nextBlock.Block);

            var op0Low  = transformContext.AllocateVirtualRegister32();
            var op0High = transformContext.AllocateVirtualRegister32();
            var op1Low  = transformContext.AllocateVirtualRegister32();
            var op1High = transformContext.AllocateVirtualRegister32();

            context.SetInstruction(IRInstruction.GetLow32, op0Low, operand1);
            context.AppendInstruction(IRInstruction.GetHigh32, op0High, operand1);
            context.AppendInstruction(IRInstruction.GetLow32, op1Low, operand2);
            context.AppendInstruction(IRInstruction.GetHigh32, op1High, operand2);

            // Compare high
            context.AppendInstruction(IRInstruction.Branch32, ConditionCode.Equal, null, op0High, op1High, newBlocks[1].Block);
            context.AppendInstruction(IRInstruction.Jmp, newBlocks[0].Block);

            // Branch if check already gave results
            if (branch == ConditionCode.Equal)
            {
                newBlocks[0].AppendInstruction(IRInstruction.Jmp, newBlocks[3].Block);
            }
            else
            {
                newBlocks[0].AppendInstruction(IRInstruction.Branch32, branch, null, op0High, op1High, newBlocks[2].Block);
                newBlocks[0].AppendInstruction(IRInstruction.Jmp, newBlocks[3].Block);
            }

            // Compare low
            newBlocks[1].AppendInstruction(IRInstruction.Branch32, branchUnsigned, null, op0Low, op1Low, newBlocks[2].Block);
            newBlocks[1].AppendInstruction(IRInstruction.Jmp, newBlocks[3].Block);

            // Success
            newBlocks[2].AppendInstruction(IRInstruction.Jmp, newBlocks[4].Block);

            // Failed
            newBlocks[3].AppendInstruction(IRInstruction.Jmp, newBlocks[4].Block);

            // Exit
            newBlocks[4].AppendInstruction(IRInstruction.Phi64, resultLow, transformContext.CreateConstant((uint)1), transformContext.ConstantZero64);
            newBlocks[4].PhiBlocks = new List <BasicBlock>(2)
            {
                newBlocks[2].Block, newBlocks[3].Block
            };
            newBlocks[4].AppendInstruction(IRInstruction.Jmp, nextBlock.Block);
        }
Beispiel #2
0
        public override void Transform(Context context, TransformContext transformContext)
        {
            Debug.Assert(context.ConditionCode != ConditionCode.Equal);

            var result   = context.Result;
            var operand1 = context.Operand1;
            var operand2 = context.Operand2;

            transformContext.SplitLongOperand(result, out Operand resultLow, out Operand resultHigh);

            var branch         = context.ConditionCode;
            var branchUnsigned = context.ConditionCode.GetUnsigned();

            var nextBlock = transformContext.Split(context);
            var newBlocks = transformContext.CreateNewBlockContexts(5, context.Label);

            TransformContext.UpdatePHIInstructionTargets(nextBlock.Block.NextBlocks, context.Block, nextBlock.Block);

            var op0Low  = transformContext.AllocateVirtualRegister32();
            var op0High = transformContext.AllocateVirtualRegister32();
            var op1Low  = transformContext.AllocateVirtualRegister32();
            var op1High = transformContext.AllocateVirtualRegister32();
            var tempLow = transformContext.AllocateVirtualRegister32();

            context.SetInstruction(IRInstruction.GetLow32, op0Low, operand1);
            context.AppendInstruction(IRInstruction.GetHigh32, op0High, operand1);
            context.AppendInstruction(IRInstruction.GetLow32, op1Low, operand2);
            context.AppendInstruction(IRInstruction.GetHigh32, op1High, operand2);

            // Compare high
            context.AppendInstruction(IRInstruction.Branch32, ConditionCode.Equal, null, op0High, op1High, newBlocks[1].Block);
            context.AppendInstruction(IRInstruction.Jmp, newBlocks[0].Block);

            newBlocks[0].AppendInstruction(IRInstruction.Branch32, branch, null, op0High, op1High, newBlocks[2].Block);
            newBlocks[0].AppendInstruction(IRInstruction.Jmp, newBlocks[3].Block);

            // Compare low
            newBlocks[1].AppendInstruction(IRInstruction.Branch32, branchUnsigned, null, op0Low, op1Low, newBlocks[2].Block);
            newBlocks[1].AppendInstruction(IRInstruction.Jmp, newBlocks[3].Block);

            // Success
            newBlocks[2].AppendInstruction(IRInstruction.Move32, tempLow, transformContext.CreateConstant((uint)1));
            newBlocks[2].AppendInstruction(IRInstruction.Jmp, newBlocks[4].Block);

            // Failed
            newBlocks[3].AppendInstruction(IRInstruction.Move32, tempLow, transformContext.ConstantZero32);
            newBlocks[3].AppendInstruction(IRInstruction.Jmp, newBlocks[4].Block);

            // Exit
            newBlocks[4].AppendInstruction(IRInstruction.Move32, resultLow, tempLow);
            newBlocks[4].AppendInstruction(IRInstruction.Move32, resultHigh, transformContext.ConstantZero32);
            newBlocks[4].AppendInstruction(IRInstruction.Jmp, nextBlock.Block);
        }
Beispiel #3
0
        public override void Transform(Context context, TransformContext transformContext)
        {
            //Debug.Assert(context.ConditionCode != ConditionCode.Equal);

            var operand1 = context.Operand1;
            var operand2 = context.Operand2;
            var target   = context.BranchTargets[0];

            var branch         = context.ConditionCode;
            var branchUnsigned = context.ConditionCode.GetUnsigned();

            var nextBlock = transformContext.Split(context);
            var newBlocks = transformContext.CreateNewBlockContexts(4, context.Label);

            // no branch
            TransformContext.UpdatePHIInstructionTargets(nextBlock.Block.NextBlocks, context.Block, nextBlock.Block);

            // Branch
            TransformContext.UpdatePHIInstructionTarget(target, context.Block, newBlocks[3].Block);

            var op0Low  = transformContext.AllocateVirtualRegister32();
            var op0High = transformContext.AllocateVirtualRegister32();
            var op1Low  = transformContext.AllocateVirtualRegister32();
            var op1High = transformContext.AllocateVirtualRegister32();

            context.SetInstruction(IRInstruction.GetLow32, op0Low, operand1);
            context.AppendInstruction(IRInstruction.GetHigh32, op0High, operand1);
            context.AppendInstruction(IRInstruction.GetLow32, op1Low, operand2);
            context.AppendInstruction(IRInstruction.GetHigh32, op1High, operand2);

            // Compare high (equal)
            context.AppendInstruction(IRInstruction.Branch32, ConditionCode.Equal, null, op0High, op1High, newBlocks[1].Block);
            context.AppendInstruction(IRInstruction.Jmp, newBlocks[0].Block);

            // Compare high
            newBlocks[0].AppendInstruction(IRInstruction.Branch32, branch, null, op0High, op1High, newBlocks[3].Block);
            newBlocks[0].AppendInstruction(IRInstruction.Jmp, newBlocks[2].Block);

            // Compare low
            newBlocks[1].AppendInstruction(IRInstruction.Branch32, branchUnsigned, null, op0Low, op1Low, newBlocks[3].Block);
            newBlocks[1].AppendInstruction(IRInstruction.Jmp, newBlocks[2].Block);

            // No branch
            newBlocks[2].AppendInstruction(IRInstruction.Jmp, nextBlock.Block);

            // Branch
            newBlocks[3].AppendInstruction(IRInstruction.Jmp, target);
        }