コード例 #1
0
        /// <summary>
        /// Searches the table for symbols with matching address values.  Ignores constants and
        /// variables.
        /// </summary>
        /// <param name="addr">Address to find.</param>
        /// <returns>First matching symbol found, or null if nothing matched.</returns>
        public Symbol FindNonVariableByAddress(int addr, OpDef.MemoryEffect effect)
        {
            bool tryRead, tryWrite;

            if (effect == OpDef.MemoryEffect.Read)
            {
                tryRead  = true;
                tryWrite = false;
            }
            else if (effect == OpDef.MemoryEffect.Write)
            {
                tryRead  = false;
                tryWrite = true;
            }
            else if (effect == OpDef.MemoryEffect.ReadModifyWrite ||
                     effect == OpDef.MemoryEffect.None)
            {
                tryRead = tryWrite = true;
            }
            else
            {
                Debug.Assert(false);
                return(null);
            }

            Symbol sym = null;

            if (tryRead)
            {
                mSymbolsByReadAddress.TryGetValue(addr, out sym);
            }
            if (tryWrite && sym == null)
            {
                mSymbolsByWriteAddress.TryGetValue(addr, out sym);
            }

            if (sym == null)
            {
                // Nothing matched, check the match groups.
                foreach (KeyValuePair <DefSymbol.MultiAddressMask, MaskGroup> kvp in mMaskGroups)
                {
                    DefSymbol.MultiAddressMask multiMask = kvp.Key;
                    if ((addr & multiMask.CompareMask) == multiMask.CompareValue)
                    {
                        MaskGroup group  = kvp.Value;
                        DefSymbol defSym = kvp.Value.Find(addr, tryRead, tryWrite);
                        if (defSym != null)
                        {
                            sym = defSym;
                            break;
                        }
                    }
                }
            }
            return(sym);
        }
コード例 #2
0
 private void AddMultiMaskEntry(DefSymbol defSym)
 {
     DefSymbol.MultiAddressMask multiMask = defSym.MultiMask;
     mMaskGroups.TryGetValue(multiMask, out MaskGroup group);
     if (group == null)
     {
         group = new MaskGroup(multiMask);
         mMaskGroups.Add(multiMask, group);
     }
     group.Add(defSym);
 }
コード例 #3
0
        /// <summary>
        /// Creates a DefSymbol from a SerDefSymbol.
        /// </summary>
        /// <param name="serDefSym">Deserialized data.</param>
        /// <param name="contentVersion">Serialization version.</param>
        /// <param name="report">Error report object.</param>
        /// <param name="outDefSym">Created symbol.</param>
        /// <returns></returns>
        private static bool CreateDefSymbol(SerDefSymbol serDefSym, int contentVersion,
                                            FileLoadReport report, out DefSymbol outDefSym)
        {
            outDefSym = null;

            if (!CreateSymbol(serDefSym, report, out Symbol sym))
            {
                return(false);
            }
            if (!CreateFormatDescriptor(serDefSym.DataDescriptor, contentVersion, report,
                                        out FormatDescriptor dfd))
            {
                return(false);
            }
            DefSymbol.DirectionFlags direction;
            if (string.IsNullOrEmpty(serDefSym.Direction))
            {
                direction = DefSymbol.DirectionFlags.ReadWrite;
            }
            else
            {
                try {
                    direction = (DefSymbol.DirectionFlags)
                                Enum.Parse(typeof(DefSymbol.DirectionFlags), serDefSym.Direction);
                } catch (ArgumentException) {
                    report.Add(FileLoadItem.Type.Warning, Res.Strings.ERR_BAD_DEF_SYMBOL_DIR +
                               ": " + serDefSym.Direction);
                    return(false);
                }
            }


            DefSymbol.MultiAddressMask multiMask = null;
            if (serDefSym.MultiMask != null)
            {
                multiMask = new DefSymbol.MultiAddressMask(serDefSym.MultiMask.CompareMask,
                                                           serDefSym.MultiMask.CompareValue, serDefSym.MultiMask.AddressMask);
            }

            outDefSym = DefSymbol.Create(sym, dfd, serDefSym.HasWidth, serDefSym.Comment,
                                         direction, multiMask);
            return(true);
        }
コード例 #4
0
 public MaskGroup(DefSymbol.MultiAddressMask multiMask)
 {
     Debug.Assert(multiMask != null);
     mMultiMask = multiMask;
 }
コード例 #5
0
        /// <summary>
        /// Parses the mask value out of a mask command line.
        /// </summary>
        /// <param name="line">Line to parse.</param>
        /// <param name="multiMask">Parsed mask value, or null if the line was empty.</param>
        /// <returns>True if the mask was parsed successfully.</returns>
        private bool ParseMask(string line, out DefSymbol.MultiAddressMask multiMask,
                               out string badMaskMsg)
        {
            Debug.Assert(line.StartsWith(MULTI_MASK_CMD));
            const int MIN = 0;
            const int MAX = 0x00ffffff;

            badMaskMsg = Res.Strings.ERR_INVALID_MULTI_MASK;
            multiMask  = null;

            string maskStr = line.Substring(MULTI_MASK_CMD.Length).Trim();

            if (string.IsNullOrEmpty(maskStr))
            {
                // empty line, disable mask
                return(true);
            }

            MatchCollection matches = sMaskRegex.Matches(maskStr);

            if (matches.Count != 1)
            {
                return(false);
            }

            string cmpMaskStr = matches[0].Groups[1].Value;
            string cmpValueStr = matches[0].Groups[2].Value;
            string addrMaskStr = matches[0].Groups[3].Value;
            int    cmpMask, cmpValue, addrMask, ignoredBase;

            if (!Asm65.Number.TryParseInt(cmpMaskStr, out cmpMask, out ignoredBase) ||
                cmpMask < MIN || cmpMask > MAX)
            {
                Debug.WriteLine("Bad cmpMask: " + cmpMaskStr);
                badMaskMsg = Res.Strings.ERR_INVALID_COMPARE_MASK;
                return(false);
            }
            if (!Asm65.Number.TryParseInt(cmpValueStr, out cmpValue, out ignoredBase) ||
                cmpValue < MIN || cmpValue > MAX)
            {
                Debug.WriteLine("Bad cmpValue: " + cmpValueStr);
                badMaskMsg = Res.Strings.ERR_INVALID_COMPARE_VALUE;
                return(false);
            }
            if (!Asm65.Number.TryParseInt(addrMaskStr, out addrMask, out ignoredBase) ||
                addrMask < MIN || addrMask > MAX)
            {
                Debug.WriteLine("Bad addrMask: " + addrMaskStr);
                badMaskMsg = Res.Strings.ERR_INVALID_ADDRESS_MASK;
                return(false);
            }

            // The two masks should not overlap: one represents bits that must be in a
            // specific state for a match to exist, the other indicates which bits are used
            // to select a specific register.  This should be a warning.
            if ((cmpMask & ~addrMask) != cmpMask)
            {
                Debug.WriteLine("Warning: cmpMask/addrMask overlap");
                badMaskMsg = Res.Strings.ERR_INVALID_CMP_ADDR_OVERLAP;
                return(false);
            }
            // If cmpValue has bits set that aren't in cmpMask, we will never find a match.
            if ((cmpValue & ~cmpMask) != 0)
            {
                Debug.WriteLine("cmpValue has unexpected bits set");
                badMaskMsg = Res.Strings.ERR_INVALID_CMP_EXTRA_BITS;
                return(false);
            }

            multiMask = new DefSymbol.MultiAddressMask(cmpMask, cmpValue, addrMask);
            return(true);
        }
コード例 #6
0
        /// <summary>
        /// Loads platform symbols.
        /// </summary>
        /// <param name="fileIdent">External file identifier of symbol file.</param>
        /// <param name="projectDir">Full path to project directory.</param>
        /// <param name="loadOrdinal">Platform file load order.</param>
        /// <param name="report">Report of warnings and errors.</param>
        /// <returns>True on success (no errors), false on failure.</returns>
        public bool LoadFromFile(string fileIdent, string projectDir, int loadOrdinal,
                                 out FileLoadReport report)
        {
            report = new FileLoadReport(fileIdent);

            ExternalFile ef = ExternalFile.CreateFromIdent(fileIdent);

            if (ef == null)
            {
                report.Add(FileLoadItem.Type.Error,
                           CommonUtil.Properties.Resources.ERR_FILE_NOT_FOUND + ": " + fileIdent);
                return(false);
            }
            string pathName = ef.GetPathName(projectDir);

            if (pathName == null)
            {
                report.Add(FileLoadItem.Type.Error,
                           Res.Strings.ERR_BAD_IDENT + ": " + fileIdent);
                return(false);
            }

            // These files shouldn't be enormous.  Just read the entire thing into a string array.
            string[] lines;
            try {
                lines = File.ReadAllLines(pathName);
            } catch (IOException ioe) {
                Debug.WriteLine("Platform symbol load failed: " + ioe);
                report.Add(FileLoadItem.Type.Error,
                           CommonUtil.Properties.Resources.ERR_FILE_NOT_FOUND + ": " + pathName);
                return(false);
            }

            string tag = string.Empty;

            DefSymbol.MultiAddressMask multiMask = null;

            int lineNum = 0;

            foreach (string line in lines)
            {
                lineNum++;      // first line is line 1, says Vim and VisualStudio
                if (string.IsNullOrEmpty(line) || line[0] == ';')
                {
                    // ignore
                }
                else if (line[0] == '*')
                {
                    if (line.StartsWith(TAG_CMD))
                    {
                        tag = ParseTag(line);
                    }
                    else if (line.StartsWith(MULTI_MASK_CMD))
                    {
                        if (!ParseMask(line, out multiMask, out string badMaskMsg))
                        {
                            report.Add(lineNum, FileLoadItem.NO_COLUMN, FileLoadItem.Type.Warning,
                                       badMaskMsg);
                        }
                        //Debug.WriteLine("Mask is now " + mask.ToString("x6"));
                    }
                    else
                    {
                        // Do something clever with *SYNOPSIS?
                        Debug.WriteLine("Ignoring CMD: " + line);
                    }
                }
                else
                {
                    MatchCollection matches = sNameValueRegex.Matches(line);
                    if (matches.Count == 1)
                    {
                        string label      = matches[0].Groups[GROUP_NAME].Value;
                        char   typeAndDir = matches[0].Groups[GROUP_TYPE].Value[0];
                        bool   isConst    = (typeAndDir == '=');
                        DefSymbol.DirectionFlags direction = DefSymbol.DirectionFlags.ReadWrite;
                        if (typeAndDir == '<')
                        {
                            direction = DefSymbol.DirectionFlags.Read;
                        }
                        else if (typeAndDir == '>')
                        {
                            direction = DefSymbol.DirectionFlags.Write;
                        }

                        string badParseMsg;
                        int    value, numBase;
                        bool   parseOk;
                        string valueStr = matches[0].Groups[GROUP_VALUE].Value;
                        if (isConst)
                        {
                            // Allow various numeric options, and preserve the value.  We
                            // don't limit the value range.
                            parseOk     = Asm65.Number.TryParseInt(valueStr, out value, out numBase);
                            badParseMsg =
                                CommonUtil.Properties.Resources.ERR_INVALID_NUMERIC_CONSTANT;
                        }
                        else if (valueStr.ToUpperInvariant().Equals(ERASE_VALUE_STR))
                        {
                            parseOk     = true;
                            value       = ERASE_VALUE;
                            numBase     = 10;
                            badParseMsg = CommonUtil.Properties.Resources.ERR_INVALID_ADDRESS;
                        }
                        else
                        {
                            // Allow things like "05/1000".  Always hex.
                            numBase = 16;
                            parseOk = Asm65.Address.ParseAddress(valueStr, (1 << 24) - 1,
                                                                 out value);
                            // limit to positive 24-bit values
                            parseOk    &= (value >= 0 && value < 0x01000000);
                            badParseMsg = CommonUtil.Properties.Resources.ERR_INVALID_ADDRESS;
                        }

                        int    width    = -1;
                        string widthStr = matches[0].Groups[GROUP_WIDTH].Value;
                        if (parseOk && !string.IsNullOrEmpty(widthStr))
                        {
                            parseOk = Asm65.Number.TryParseInt(widthStr, out width,
                                                               out int ignoredBase);
                            if (parseOk)
                            {
                                if (width < DefSymbol.MIN_WIDTH || width > DefSymbol.MAX_WIDTH)
                                {
                                    parseOk     = false;
                                    badParseMsg = Res.Strings.ERR_INVALID_WIDTH;
                                }
                            }
                            else
                            {
                                badParseMsg =
                                    CommonUtil.Properties.Resources.ERR_INVALID_NUMERIC_CONSTANT;
                            }
                        }

                        if (parseOk && multiMask != null && !isConst)
                        {
                            // We need to ensure that all possible values fit within the mask.
                            // We don't test AddressValue here, because it's okay for the
                            // canonical value to be outside the masked range.
                            int testWidth = (width > 0) ? width : 1;
                            for (int testValue = value; testValue < value + testWidth; testValue++)
                            {
                                if ((testValue & multiMask.CompareMask) != multiMask.CompareValue)
                                {
                                    parseOk     = false;
                                    badParseMsg = Res.Strings.ERR_VALUE_INCOMPATIBLE_WITH_MASK;
                                    Debug.WriteLine("Mask FAIL: value=" + value.ToString("x6") +
                                                    " width=" + width +
                                                    " testValue=" + testValue.ToString("x6") +
                                                    " mask=" + multiMask);
                                    break;
                                }
                            }
                        }

                        if (!parseOk)
                        {
                            report.Add(lineNum, FileLoadItem.NO_COLUMN, FileLoadItem.Type.Warning,
                                       badParseMsg);
                        }
                        else
                        {
                            string comment = matches[0].Groups[GROUP_COMMENT].Value;
                            if (comment.Length > 0)
                            {
                                // remove ';'
                                comment = comment.Substring(1);
                            }
                            FormatDescriptor.SubType subType =
                                FormatDescriptor.GetSubTypeForBase(numBase);
                            DefSymbol symDef = new DefSymbol(label, value, Symbol.Source.Platform,
                                                             isConst ? Symbol.Type.Constant : Symbol.Type.ExternalAddr,
                                                             subType, width, width > 0, comment, direction, multiMask,
                                                             tag, loadOrdinal, fileIdent);
                            if (mSymbols.ContainsKey(label))
                            {
                                // This is very easy to do -- just define the same symbol twice
                                // in the same file.  We don't really need to do anything about
                                // it though.
                                Debug.WriteLine("NOTE: stomping previous definition of " + label);
                            }
                            mSymbols[label] = symDef;
                        }
                    }
                    else
                    {
                        report.Add(lineNum, FileLoadItem.NO_COLUMN, FileLoadItem.Type.Warning,
                                   CommonUtil.Properties.Resources.ERR_SYNTAX);
                    }
                }
            }

            return(!report.HasErrors);
        }
コード例 #7
0
 public SerMultiMask(DefSymbol.MultiAddressMask multiMask)
 {
     CompareMask  = multiMask.CompareMask;
     CompareValue = multiMask.CompareValue;
     AddressMask  = multiMask.AddressMask;
 }