Example #1
0
		private AstNodeExprLValue BranchFlag()
		{
#if true
			if (BranchFlagLocal == null)
			{
				BranchFlagLocal = AstLocal.Create(MipsMethodEmitter.ILGenerator, typeof(bool), "BranchFlag");
			}
			return ast.Local(BranchFlagLocal);
#else
			return REG("BranchFlag");
#endif
		}
 public AstNodeExprLocal(AstLocal AstLocal)
 {
     this.AstLocal = AstLocal;
 }
Example #3
0
 public void WriteLocal(AstLocal local, AstExpression value)
 {
     AddStatement(
         AstFactory.WriteLocalStatement(local, value));
 }
        protected virtual void _Generate(AstNodeStmSwitch Switch)
        {
            var allCaseValues = Switch.Cases.Select(Case => Case.CaseValue);
            var caseValues    = allCaseValues as IList <object> ?? allCaseValues.ToList();

            if (caseValues.Count != caseValues.Distinct().Count())
            {
                throw new Exception("Repeated case in switch!");
            }

            // Check types and unique values.

            var endCasesLabel = AstLabel.CreateLabel("EndCasesLabel");
            var defaultLabel  = AstLabel.CreateLabel("DefaultLabel");

            if (Switch.Cases.Length > 0)
            {
                var commonType = Switch.Cases.First().CaseValue.GetType();
                if (Switch.Cases.Any(Case => Case.CaseValue.GetType() != commonType))
                {
                    throw new Exception("All cases should have the same type");
                }

                var doneSpecialized = false;

                // Specialized constant-time integer switch (if possible)
                if (AstUtils.IsIntegerType(commonType))
                {
                    var commonMin   = Switch.Cases.Min(Case => AstUtils.CastType <long>(Case.CaseValue));
                    var commonMax   = Switch.Cases.Max(Case => AstUtils.CastType <long>(Case.CaseValue));
                    var casesLength = commonMax - commonMin + 1;

                    // No processing tables greater than 4096 elements.
                    if (casesLength <= 4096)
                    {
                        var labels = new AstLabel[casesLength];
                        for (var n = 0; n < casesLength; n++)
                        {
                            labels[n] = defaultLabel;
                        }

                        foreach (var Case in Switch.Cases)
                        {
                            var realValue = AstUtils.CastType <long>(Case.CaseValue);
                            var offset    = realValue - commonMin;
                            labels[offset] = AstLabel.CreateLabel("Case_" + realValue);
                        }

                        /*
                         * //var SwitchVarLocal = AstLocal.Create(AllCaseValues.First().GetType(), "SwitchVarLocal" + SwitchVarCount++);
                         * //Generate(new AstNodeStmAssign(new AstNodeExprLocal(SwitchVarLocal), Switch.SwitchValue - new AstNodeExprCast(CommonType, CommonMin)));
                         * //Generate(new AstNodeStmIfElse(new AstNodeExprBinop(new AstNodeExprLocal(SwitchVarLocal), "<", 0), new AstNodeStmGotoAlways(DefaultLabel)));
                         * //Generate(new AstNodeStmIfElse(new AstNodeExprBinop(new AstNodeExprLocal(SwitchVarLocal), ">=", CasesLength), new AstNodeStmGotoAlways(DefaultLabel)));
                         * //Generate(new AstNodeExprLocal(SwitchVarLocal));
                         */

                        Generate(Switch.SwitchValue - new AstNodeExprCast(commonType, commonMin));
                        Emit(OpCodes.Switch, labels);
                        Generate(new AstNodeStmGotoAlways(defaultLabel));
                        foreach (var Case in Switch.Cases)
                        {
                            var realValue = AstUtils.CastType <long>(Case.CaseValue);
                            var offset    = realValue - commonMin;
                            Generate(new AstNodeStmLabel(labels[offset]));
                            {
                                Generate(Case.Code);
                            }
                            Generate(new AstNodeStmGotoAlways(endCasesLabel));
                        }

                        doneSpecialized = true;
                    }
                    else
                    {
                        // TODO: find a common shift and masks for all the values to reduce CasesLength.
                        // TODO: On too large test cases, split them recursively in:
                        // if (Var < Half) { switch(Var - LowerPartMin) { ... } } else { switch(Var - Half - UpperPartMin) { ... } }
                    }
                }
                // Specialized switch for strings (checking length, then hash, then contents)
                else if (commonType == typeof(string))
                {
                    // TODO!
                }

                // Generic if/else
                if (!doneSpecialized)
                {
                    var switchVarLocal =
                        AstLocal.Create(caseValues.First().GetType(), "SwitchVarLocal" + _switchVarCount++);
                    Generate(new AstNodeStmAssign(new AstNodeExprLocal(switchVarLocal), Switch.SwitchValue));
                    //Switch.Cases
                    foreach (var Case in Switch.Cases)
                    {
                        var labelSkipThisCase = AstLabel.CreateLabel("LabelCase" + Case.CaseValue);
                        Generate(new AstNodeStmGotoIfFalse(labelSkipThisCase,
                                                           new AstNodeExprBinop(new AstNodeExprLocal(switchVarLocal), "==",
                                                                                new AstNodeExprImm(Case.CaseValue))));
                        Generate(Case.Code);
                        Generate(new AstNodeStmGotoAlways(endCasesLabel));
                        Generate(new AstNodeStmLabel(labelSkipThisCase));
                    }
                }
            }

            Generate(new AstNodeStmLabel(defaultLabel));
            if (Switch.CaseDefault != null)
            {
                Generate(Switch.CaseDefault.Code);
            }

            Generate(new AstNodeStmLabel(endCasesLabel));
        }
Example #5
0
 public void WriteLocal(AstLocal a)
 {
     WriteIdentifier(a.Name);
 }
Example #6
0
 public AstNodeExprLocal(AstLocal AstLocal)
 {
     this.AstLocal = AstLocal;
 }
        public AstNodeStm Vcmp()
        {
            var vectorSize = _instruction.OneTwo;
            var cond       = _instruction.Imm4;
            var cond2      = (ConditionEnum)cond;
            //bool NormalFlag = (Cond & 8) == 0;
            //bool NotFlag = (Cond & 4) != 0;
            //uint TypeFlag = (Cond & 3);

            var localCcTemp = _ast.Local(AstLocal.Create <bool>());
            var localCcOr   = _ast.Local(AstLocal.Create <bool>());
            var localCcAnd  = _ast.Local(AstLocal.Create <bool>());

            return(_ast.Statements(
                       _ast.Assign(localCcOr, false),
                       _ast.Assign(localCcAnd, true),

                       // TODO: CHECK THIS!
                       _ast.AssignVcc(0, true),
                       _ast.AssignVcc(1, true),
                       _ast.AssignVcc(2, true),
                       _ast.AssignVcc(3, true),
                       _List(vectorSize, index =>
            {
                AstNodeExpr expr;
                //bool UsedForAggregate;

                var left = VecVs[index];
                var right = VecVt[index];
                switch (cond2)
                {
                case ConditionEnum.VcFl:
                    expr = _ast.Immediate(false);
                    break;

                case ConditionEnum.VcEq:
                    expr = _ast.Binary(left, "==", right);
                    break;

                case ConditionEnum.VcLt:
                    expr = _ast.Binary(left, "<", right);
                    break;

                //case ConditionEnum.VC_LE: Expr = ast.Binary(Left, "<=", Right); break;
                case ConditionEnum.VcLe:
                    expr = _ast.CallStatic((Func <float, float, bool>)MathFloat.IsLessOrEqualsThan, left,
                                           right);
                    break;

                case ConditionEnum.VcTr:
                    expr = _ast.Immediate(true);
                    break;

                case ConditionEnum.VcNe:
                    expr = _ast.Binary(left, "!=", right);
                    break;

                //case ConditionEnum.VC_GE: Expr = ast.Binary(Left, ">=", Right); break;
                case ConditionEnum.VcGe:
                    expr = _ast.CallStatic((Func <float, float, bool>)MathFloat.IsGreatOrEqualsThan, left,
                                           right);
                    break;

                case ConditionEnum.VcGt:
                    expr = _ast.Binary(left, ">", right);
                    break;

                case ConditionEnum.VcEz:
                    expr = _ast.Binary(_ast.Binary(left, "==", 0.0f), "||", _ast.Binary(left, "==", -0.0f));
                    break;

                case ConditionEnum.VcEn:
                    expr = _ast.CallStatic((Func <float, bool>)MathFloat.IsNan, left);
                    break;

                case ConditionEnum.VcEi:
                    expr = _ast.CallStatic((Func <float, bool>)MathFloat.IsInfinity, left);
                    break;

                case ConditionEnum.VcEs:
                    expr = _ast.CallStatic((Func <float, bool>)MathFloat.IsNanOrInfinity, left);
                    break;         // Tekken Dark Resurrection

                case ConditionEnum.VcNz:
                    expr = _ast.Binary(left, "!=", 0f);
                    break;

                case ConditionEnum.VcNn:
                    expr = _ast.Unary("!", _ast.CallStatic((Func <float, bool>)MathFloat.IsNan, left));
                    break;

                case ConditionEnum.VcNi:
                    expr = _ast.Unary("!", _ast.CallStatic((Func <float, bool>)MathFloat.IsInfinity, left));
                    break;

                case ConditionEnum.VcNs:
                    expr = _ast.Unary("!",
                                      _ast.CallStatic((Func <float, bool>)MathFloat.IsNanOrInfinity, left));
                    break;

                default: throw (new InvalidOperationException());
                }

                return _ast.Statements(new List <AstNodeStm>
                {
                    _ast.Assign(localCcTemp, expr),
                    _ast.AssignVcc(index, localCcTemp),
                    _ast.Assign(localCcOr, _ast.Binary(localCcOr, "||", localCcTemp)),
                    _ast.Assign(localCcAnd, _ast.Binary(localCcAnd, "&&", localCcTemp))
                });
            }),
                       _ast.AssignVcc(4, localCcOr),
                       _ast.AssignVcc(5, localCcAnd)
                       ));
        }
 private AstNodeExprLValue BranchFlag()
 {
     if (_DynarecConfig.BranchFlagAsLocal)
     {
         if (BranchFlagLocal == null)
         {
             BranchFlagLocal = AstLocal.Create<bool>("BranchFlag");
         }
         return ast.Local(BranchFlagLocal);
     }
     else
     {
         return ast.BranchFlag();
     }
 }