private static bool ValueMatches(int value, int comparisonValue, RequirementOperator comparisonType) { switch (comparisonType) { case RequirementOperator.None: return(true); case RequirementOperator.Equal: return(value == comparisonValue); case RequirementOperator.NotEqual: return(value != comparisonValue); case RequirementOperator.LessThan: return(value < comparisonValue); case RequirementOperator.LessThanOrEqual: return(value <= comparisonValue); case RequirementOperator.GreaterThan: return(value > comparisonValue); case RequirementOperator.GreaterThanOrEqual: return(value >= comparisonValue); default: return(false); } }
public void TestToString(RequirementType requirementType, TestField left, RequirementOperator requirementOperator, TestField right, int hitCount, string expected) { var requirement = new Requirement { Type = requirementType, Left = GetField(left), Operator = requirementOperator, Right = GetField(right), HitCount = (uint)hitCount }; Assert.That(requirement.ToString(), Is.EqualTo(expected)); }
/// <summary> /// Gets the logically opposing operator. /// </summary> public static RequirementOperator GetOpposingOperator(RequirementOperator op) { switch (op) { case RequirementOperator.Equal: return(RequirementOperator.NotEqual); case RequirementOperator.NotEqual: return(RequirementOperator.Equal); case RequirementOperator.LessThan: return(RequirementOperator.GreaterThanOrEqual); case RequirementOperator.LessThanOrEqual: return(RequirementOperator.GreaterThan); case RequirementOperator.GreaterThan: return(RequirementOperator.LessThanOrEqual); case RequirementOperator.GreaterThanOrEqual: return(RequirementOperator.LessThan); default: return(RequirementOperator.None); } }
private static RequirementOperator GetReversedRequirementOperator(RequirementOperator op) { switch (op) { case RequirementOperator.Equal: return(RequirementOperator.Equal); case RequirementOperator.NotEqual: return(RequirementOperator.NotEqual); case RequirementOperator.LessThan: return(RequirementOperator.GreaterThan); case RequirementOperator.LessThanOrEqual: return(RequirementOperator.GreaterThanOrEqual); case RequirementOperator.GreaterThan: return(RequirementOperator.LessThan); case RequirementOperator.GreaterThanOrEqual: return(RequirementOperator.LessThanOrEqual); default: return(RequirementOperator.None); } }
private static ParseErrorExpression HandleAddAddressComparison(ExpressionBase comparison, IList <Requirement> requirements, RequirementOperator op, Requirement extraRequirement) { // determine how long the AddAddress chain is var rightIndex = requirements.Count; while (requirements[rightIndex - 1].Type == RequirementType.AddAddress) { rightIndex--; } // attempt to match the AddAddress chain with the previous conditions bool match = true; var distance = requirements.Count - rightIndex; var leftIndex = rightIndex - 1; var leftStop = leftIndex - distance; var requirement = requirements[leftIndex]; // last element of left side while (leftIndex > leftStop) { // if the AddAddress portion doesn't match, skip over any remaining AddAddresses // for the previous condition, and bail if (requirements[leftIndex - 1] != requirements[leftIndex + distance]) { while (leftIndex > 0 && requirements[leftIndex - 1].Type == RequirementType.AddAddress) { --leftIndex; } match = false; break; } --leftIndex; } // if the AddAddress chains match, then merge the conditions if (match) { while (requirements.Count > rightIndex) { requirements.RemoveAt(requirements.Count - 1); } requirement.Operator = op; requirement.Right = extraRequirement.Left; return(null); } // put the extra requirement back. we couldn't merge it with the left condition requirements.Add(extraRequirement); // AddAddress chains were not the same. Attempt to rearrange the logic using SubSource // (if A cannot be moved) (if A can be moved) // A == B ~> A - B + 0 == 0 ~> B - A == 0 ~> -A + B == 0 // A != B ~> A - B + 0 != 0 ~> B - A != 0 ~> -A + B != 0 // A > B ~> A - B + M > M ~> B - A < 0 ~> -A + B > M [leverage underflow] // A >= B ~> A - B + M >= M ~> B - A <= 0 ~> -A - 1 + B >= M [leverage underflow] // A < B ~> A - B + 0 > M ~> B - A + M > M ~> -A + B + M > M [avoid underflow] // A <= B ~> A - B + 0 >= M ~> B - A + M >= M ~> -A + B + M >= M [avoid underflow] // calculate M uint maxValue = 0; if (op != RequirementOperator.Equal && op != RequirementOperator.NotEqual) { maxValue = Math.Max(Field.GetMaxValue(requirement.Left.Size), Field.GetMaxValue(extraRequirement.Left.Size)); if (maxValue == 0xFFFFFFFF) { return(new ParseErrorExpression("Indirect memory addresses must match on both sides of a comparison for 32-bit values", comparison)); } } // if A is preceded by an AddSource or SubSource, we can't change it to a SubSource Requirement prevReq = null; bool cannotBeChanged = false; if (leftIndex > 0) { prevReq = requirements[leftIndex - 1]; cannotBeChanged = (prevReq.Type == RequirementType.AddSource || prevReq.Type == RequirementType.SubSource); } if (cannotBeChanged) { requirement.Type = RequirementType.AddSource; extraRequirement.Type = RequirementType.SubSource; uint leftValue = 0; switch (op) { case RequirementOperator.GreaterThan: case RequirementOperator.GreaterThanOrEqual: leftValue = maxValue; break; case RequirementOperator.LessThan: op = RequirementOperator.GreaterThan; break; case RequirementOperator.LessThanOrEqual: op = RequirementOperator.GreaterThanOrEqual; break; } // if preceeded by a constant, merge the constant into the final condition if (prevReq.Left.Type == FieldType.Value) { if (prevReq.Type == RequirementType.AddSource) { leftValue += prevReq.Left.Value; } else if (prevReq.Left.Value < leftValue) { leftValue -= prevReq.Left.Value; } else { maxValue += prevReq.Left.Value; } requirements.RemoveAt(leftIndex - 1); } extraRequirement = new Requirement(); extraRequirement.Left = new Field { Type = FieldType.Value, Value = leftValue }; extraRequirement.Operator = op; extraRequirement.Right = new Field { Type = FieldType.Value, Value = maxValue }; requirements.Add(extraRequirement); return(null); } // if A can be changed, make it a SubSource requirement.Type = RequirementType.SubSource; switch (op) { case RequirementOperator.GreaterThanOrEqual: // -A - 1 + B >= M // subtract 1 from (B-A) in case B==A, so the result will still be negative requirements.Insert(rightIndex, new Requirement { Type = RequirementType.SubSource, Left = new Field { Type = FieldType.Value, Value = 1 } }); goto case RequirementOperator.GreaterThan; case RequirementOperator.Equal: // -A + B == 0 case RequirementOperator.NotEqual: // -A + B != 0 case RequirementOperator.GreaterThan: // -A + B > M extraRequirement.Operator = op; extraRequirement.Right = new Field { Type = FieldType.Value, Value = maxValue }; break; case RequirementOperator.LessThan: // -A + B + M > M case RequirementOperator.LessThanOrEqual: // -A + B + M >= M extraRequirement.Type = RequirementType.AddSource; extraRequirement = new Requirement(); extraRequirement.Left = extraRequirement.Right = new Field { Type = FieldType.Value, Value = maxValue }; extraRequirement.Operator = (op == RequirementOperator.LessThan) ? RequirementOperator.GreaterThan : RequirementOperator.GreaterThanOrEqual; requirements.Add(extraRequirement); break; } return(null); }
public void TestAppendStringHex(RequirementType requirementType, TestField left, RequirementOperator requirementOperator, TestField right, int hitCount, string expected) { var requirement = new Requirement { Type = requirementType, Left = GetField(left), Operator = requirementOperator, Right = GetField(right), HitCount = (uint)hitCount }; var builder = new StringBuilder(); requirement.AppendString(builder, NumberFormat.Hexadecimal); Assert.That(builder.ToString(), Is.EqualTo(expected)); }
public bool Parse(out int number, out RequirementOperator comparison) { string expression = Text; int index = 0; if (String.IsNullOrEmpty(expression)) { number = 0; comparison = RequirementOperator.None; return(true); } switch (expression[0]) { case '<': ++index; if (expression[index] == '=') { ++index; comparison = RequirementOperator.LessThanOrEqual; } else { comparison = RequirementOperator.LessThan; } break; case '>': ++index; if (expression[index] == '=') { ++index; comparison = RequirementOperator.GreaterThanOrEqual; } else { comparison = RequirementOperator.GreaterThan; } break; case '!': ++index; if (expression[index] == '=') { ++index; } comparison = RequirementOperator.NotEqual; break; case '=': ++index; if (expression[index] == '=') { ++index; } comparison = RequirementOperator.Equal; break; default: comparison = RequirementOperator.Equal; break; } if (index > 0) { expression = expression.Substring(index); } return(Int32.TryParse(expression, out number)); }
protected ParseErrorExpression BuildTrigger(TriggerBuilderContext context, InterpreterScope scope, FunctionCallExpression functionCall, ExpressionBase address) { var requirement = new Requirement(); var integerConstant = address as IntegerConstantExpression; if (integerConstant != null) { requirement.Left = new Field { Size = this.Size, Type = FieldType.MemoryAddress, Value = (uint)integerConstant.Value }; context.Trigger.Add(requirement); return(null); } IntegerConstantExpression offsetConstant = null; IntegerConstantExpression scalarConstant = null; RequirementOperator scalarOperation = RequirementOperator.None; var originalAddress = address; var funcCall = address as FunctionCallExpression; if (funcCall == null) { var mathematic = address as MathematicExpression; if (mathematic != null && (mathematic.Operation == MathematicOperation.Add || mathematic.Operation == MathematicOperation.Subtract)) { if (CountMathematicMemoryAccessors(mathematic, 2) >= 2) { return(new ParseErrorExpression("Cannot construct single address lookup from multiple memory references", address)); } offsetConstant = mathematic.Right as IntegerConstantExpression; if (offsetConstant != null) { address = mathematic.Left; } else { offsetConstant = mathematic.Left as IntegerConstantExpression; if (offsetConstant != null) { address = mathematic.Right; } } if (offsetConstant != null) { if (mathematic.Operation == MathematicOperation.Subtract) { offsetConstant = new IntegerConstantExpression(-offsetConstant.Value); } } mathematic = address as MathematicExpression; } if (mathematic != null) { switch (mathematic.Operation) { case MathematicOperation.Multiply: scalarConstant = mathematic.Right as IntegerConstantExpression; if (scalarConstant != null) { address = mathematic.Left; scalarOperation = RequirementOperator.Multiply; } else { scalarConstant = mathematic.Left as IntegerConstantExpression; if (scalarConstant != null) { scalarOperation = RequirementOperator.Multiply; address = mathematic.Right; } } break; case MathematicOperation.Divide: scalarConstant = mathematic.Right as IntegerConstantExpression; if (scalarConstant != null) { address = mathematic.Left; scalarOperation = RequirementOperator.Divide; } break; case MathematicOperation.BitwiseAnd: scalarConstant = mathematic.Right as IntegerConstantExpression; if (scalarConstant != null) { address = mathematic.Left; scalarOperation = RequirementOperator.BitwiseAnd; } break; } } funcCall = address as FunctionCallExpression; } if (funcCall != null) { var funcDef = scope.GetFunction(funcCall.FunctionName.Name) as TriggerBuilderContext.FunctionDefinition; if (funcDef != null) { if (funcDef is MemoryAccessorFunction || funcDef is PrevPriorFunction) { var error = funcDef.BuildTrigger(context, scope, funcCall); if (error != null) { return(error); } var lastRequirement = context.LastRequirement; lastRequirement.Type = RequirementType.AddAddress; if (scalarConstant != null && scalarConstant.Value != 1) { lastRequirement.Operator = scalarOperation; lastRequirement.Right = new Field { Size = FieldSize.DWord, Type = FieldType.Value, Value = (uint)scalarConstant.Value }; } // a memory reference without an offset has to be generated with a 0 offset. uint offset = (offsetConstant != null) ? (uint)offsetConstant.Value : 0; requirement.Left = new Field { Size = this.Size, Type = FieldType.MemoryAddress, Value = offset }; context.Trigger.Add(requirement); return(null); } } } var builder = new StringBuilder(); builder.Append("Cannot convert to an address: "); originalAddress.AppendString(builder); return(new ParseErrorExpression(builder.ToString(), address)); }