Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        /// <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);
            }
        }
Beispiel #4
0
        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);
        }
Beispiel #6
0
        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));
        }
Beispiel #7
0
            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));
        }