Esempio n. 1
0
        public void EmitCondBranch(ILLabel target, Condition cond)
        {
            if (_optOpLastCompare != null &&
                _optOpLastCompare == _optOpLastFlagSet && _branchOps.ContainsKey(cond))
            {
                if (_optOpLastCompare.Emitter == InstEmit.Subs)
                {
                    Ldloc(CmpOptTmp1Index, RegisterType.Int, _optOpLastCompare.RegisterSize);
                    Ldloc(CmpOptTmp2Index, RegisterType.Int, _optOpLastCompare.RegisterSize);

                    Emit(_branchOps[cond], target);

                    return;
                }
                else if (_optOpLastCompare.Emitter == InstEmit.Adds && cond != Condition.GeUn &&
                         cond != Condition.LtUn &&
                         cond != Condition.GtUn &&
                         cond != Condition.LeUn)
                {
                    //There are several limitations that needs to be taken into account for CMN comparisons:
                    //- The unsigned comparisons are not valid, as they depend on the
                    //carry flag value, and they will have different values for addition and
                    //subtraction. For addition, it's carry, and for subtraction, it's borrow.
                    //So, we need to make sure we're not doing a unsigned compare for the CMN case.
                    //- We can only do the optimization for the immediate variants,
                    //because when the second operand value is exactly INT_MIN, we can't
                    //negate the value as theres no positive counterpart.
                    //Such invalid values can't be encoded on the immediate encodings.
                    if (_optOpLastCompare is IOpCodeAluImm64 op)
                    {
                        Ldloc(CmpOptTmp1Index, RegisterType.Int, _optOpLastCompare.RegisterSize);

                        if (_optOpLastCompare.RegisterSize == RegisterSize.Int32)
                        {
                            EmitLdc_I4((int)-op.Imm);
                        }
                        else
                        {
                            EmitLdc_I8(-op.Imm);
                        }

                        Emit(_branchOps[cond], target);

                        return;
                    }
                }
            }

            OpCode ilOp;

            int intCond = (int)cond;

            if (intCond < 14)
            {
                int condTrue = intCond >> 1;

                switch (condTrue)
                {
                case 0: EmitLdflg((int)PState.ZBit); break;

                case 1: EmitLdflg((int)PState.CBit); break;

                case 2: EmitLdflg((int)PState.NBit); break;

                case 3: EmitLdflg((int)PState.VBit); break;

                case 4:
                    EmitLdflg((int)PState.CBit);
                    EmitLdflg((int)PState.ZBit);

                    Emit(OpCodes.Not);
                    Emit(OpCodes.And);
                    break;

                case 5:
                case 6:
                    EmitLdflg((int)PState.NBit);
                    EmitLdflg((int)PState.VBit);

                    Emit(OpCodes.Ceq);

                    if (condTrue == 6)
                    {
                        EmitLdflg((int)PState.ZBit);

                        Emit(OpCodes.Not);
                        Emit(OpCodes.And);
                    }
                    break;
                }

                ilOp = (intCond & 1) != 0 ? OpCodes.Brfalse : OpCodes.Brtrue;
            }
            else
            {
                ilOp = OpCodes.Br;
            }

            Emit(ilOp, target);
        }
Esempio n. 2
0
 public void Emit(OpCode ilOp, ILLabel label)
 {
     _ilBlock.Add(new ILOpCodeBranch(ilOp, label));
 }
Esempio n. 3
0
        public void EmitCondBranch(ILLabel target, Condition cond)
        {
            OpCode ilOp;

            int intCond = (int)cond;

            if (_optOpLastCompare != null &&
                _optOpLastCompare == _optOpLastFlagSet && _branchOps.ContainsKey(cond))
            {
                Ldloc(CmpOptTmp1Index, IoType.Int, _optOpLastCompare.RegisterSize);
                Ldloc(CmpOptTmp2Index, IoType.Int, _optOpLastCompare.RegisterSize);

                ilOp = _branchOps[cond];
            }
            else if (intCond < 14)
            {
                int condTrue = intCond >> 1;

                switch (condTrue)
                {
                case 0: EmitLdflg((int)PState.ZBit); break;

                case 1: EmitLdflg((int)PState.CBit); break;

                case 2: EmitLdflg((int)PState.NBit); break;

                case 3: EmitLdflg((int)PState.VBit); break;

                case 4:
                    EmitLdflg((int)PState.CBit);
                    EmitLdflg((int)PState.ZBit);

                    Emit(OpCodes.Not);
                    Emit(OpCodes.And);
                    break;

                case 5:
                case 6:
                    EmitLdflg((int)PState.NBit);
                    EmitLdflg((int)PState.VBit);

                    Emit(OpCodes.Ceq);

                    if (condTrue == 6)
                    {
                        EmitLdflg((int)PState.ZBit);

                        Emit(OpCodes.Not);
                        Emit(OpCodes.And);
                    }
                    break;
                }

                ilOp = (intCond & 1) != 0
                    ? OpCodes.Brfalse
                    : OpCodes.Brtrue;
            }
            else
            {
                ilOp = OpCodes.Br;
            }

            Emit(ilOp, target);
        }
Esempio n. 4
0
 public void MarkLabel(ILLabel label)
 {
     _ilBlock.Add(label);
 }
Esempio n. 5
0
 public ILOpCodeBranch(OpCode ilOp, ILLabel label)
 {
     _ilOp  = ilOp;
     _label = label;
 }