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; }
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)); }
public void WriteLocal(AstLocal a) { WriteIdentifier(a.Name); }
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(); } }