Пример #1
0
        public static List <String> ParseFile(string file, ref List <FileParserException> fpx, int desiredMifSize)
        {
            InstructionParser        iParse          = new InstructionParser();
            Dictionary <string, int> SubroutineTable = new Dictionary <string, int>();

            List <SRCInstruction> instructionsToReparse = new List <SRCInstruction>();

            List <String> outList = new List <string>();

            int memoryLocation = 0;

            string[] inputFile = File.ReadAllLines(file);

            for (int i = 0; i < inputFile.Length; i++)
            {
                string trimmed = TrimWhiteSpace(inputFile[i].Split(';')[0].Trim());
                string result  = "";

                if (trimmed.ToLower().StartsWith("org"))
                {
                    try
                    {
                        //memory origin designation
                        string memLoc    = trimmed.ToLower().Split(' ')[1];
                        int    actualLoc = 0;

                        if (memLoc.StartsWith("$"))
                        {
                            memLoc    = memLoc.TrimStart('$');
                            actualLoc = Convert.ToInt32(memLoc, 16);
                        }
                        else if (memLoc.StartsWith("0x"))
                        {
                            actualLoc = Convert.ToInt32(memLoc, 16);
                        }
                        else
                        {
                            actualLoc = Convert.ToInt32(memLoc);
                        }



                        if (actualLoc == memoryLocation)
                        {
                            fpx.Add(new FileParserException("Ignoring org directive '" + trimmed + "' : Erroneous.", i, 1));
                        }
                        else if (actualLoc < memoryLocation)
                        {
                            fpx.Add(new FileParserException("Ignoring org directive '" + trimmed + "' : Can't go backwards in memory.", i, 1));
                        }
                        else if (actualLoc - 1 == memoryLocation)
                        {
                            StringBuilder s = new StringBuilder();
                            s.AppendFormat("{0} : 00000000;", String.Format("{0:X}", actualLoc - 1));
                            result = s.ToString();
                            outList.Add(result);
                            memoryLocation = actualLoc;
                        }
                        else
                        {
                            StringBuilder s = new StringBuilder();
                            s.AppendFormat("[{0}..{1}] : 00000000;", String.Format("{0:X}", memoryLocation), String.Format("{0:X}", actualLoc - 1));
                            result = s.ToString();
                            outList.Add(result);
                            memoryLocation = actualLoc;
                        }
                    }
                    catch (Exception ex)
                    {
                        fpx.Add(new FileParserException("Error parsing org directive '" + trimmed + "' : " + ex.Message, i, 0));
                    }
                }
                else if (trimmed.StartsWith("@"))//subroutine
                {
                    SubroutineTable.Add(trimmed, memoryLocation);

                    fpx.Add(new FileParserException("Subroutine Found at location " + String.Format("{0:X}", memoryLocation) + " '" + trimmed + "'", i, 2));
                }
                else if (trimmed.StartsWith("&"))//data spec
                {
                    string[] dataItems = trimmed.Remove(0, 1).Replace(' ', ',').Split(',');

                    for (int j = 0; j < dataItems.Length; j++)
                    {
                        string dataItem;

                        try
                        {
                            if (dataItems[j].StartsWith("$"))
                            {
                                dataItem = dataItems[j].TrimStart('$');
                                dataItem = Convert.ToInt32(dataItem, 16).ToString("X");
                            }
                            else if (dataItems[j].ToLower().StartsWith("0x"))
                            {
                                dataItem = Convert.ToInt32(dataItems[j], 16).ToString("X");
                            }
                            else
                            {
                                dataItem = Convert.ToInt32(dataItems[j]).ToString("X");
                            }

                            StringBuilder s = new StringBuilder();
                            s.AppendFormat("{0} : {1};", String.Format("{0:X}", memoryLocation++), dataItem);
                            result = s.ToString();
                            outList.Add(result);
                        }
                        catch (Exception ex)
                        {
                            fpx.Add(new FileParserException("Error parsing data item '" + dataItems[j] + "' : " + ex.Message, i, 0));
                            throw;
                        }
                    }
                }
                else if (String.IsNullOrWhiteSpace(trimmed))
                {
                    //do nothing- this is a comment or other such line
                }
                else
                {
                    //intsruction! Yay!
                    try
                    {
                        SRCInstruction outputInst = iParse.ParseInstruction(trimmed);
                        StringBuilder  s          = new StringBuilder();

                        if (outputInst.replaceImmediateWithAddress)
                        {
                            //... do this
                            instructionsToReparse.Add(outputInst);
                            int instructionIdx = instructionsToReparse.Count - 1;
                            s.AppendFormat("{0} : REPARSEINSTRUCTION_{1};", String.Format("{0:X}", memoryLocation++), instructionIdx);
                        }
                        else
                        {
                            string tmpResult = outputInst.outputInstructionString.PadLeft(8, '0');
                            s.AppendFormat("{0} : {1};", String.Format("{0:X}", memoryLocation++), tmpResult);
                        }

                        result = s.ToString();
                        outList.Add(result);
                    }
                    catch (Exception ex)
                    {
                        fpx.Add(new FileParserException("Error parsing instruction '" + trimmed + "' : " + ex.Message, i, 0));
                    }
                }
            }

            //return outList;
            //loop thru outList and find the memory locations to replace....
            for (int i = 0; i < outList.Count; i++)
            {
                if (outList[i].Contains("REPARSEINSTRUCTION"))
                {
                    //we gotta reparse this shit!
                    string reparseMarker = outList[i].Split(':')[1].Trim(' ').Trim(';');
                    int    reparseIdx    = Convert.ToInt32(reparseMarker.Split('_')[1]);

                    SRCInstruction reparseInst = instructionsToReparse[reparseIdx];

                    try
                    {
                        string replacementMemoryLocation = "0x" + SubroutineTable[reparseInst.immediateToReplace].ToString("X");
                        string replacementInstruction    = reparseInst.originalInstructionString.Replace(reparseInst.immediateToReplace, replacementMemoryLocation);

                        SRCInstruction newInstruction = iParse.ParseInstruction(replacementInstruction);
                        string         tmpResult      = newInstruction.outputInstructionString.PadLeft(8, '0');

                        outList[i] = outList[i].Replace(reparseMarker, tmpResult);
                    }
                    catch (Exception ex)
                    {
                        fpx.Add(new FileParserException("Error parsing instruction (2nd pass)'" + outList[i] + "' : " + ex.Message, i, 0));
                    }
                }
            }

            int pow = 0;

            while (desiredMifSize > (int)Math.Pow(2, pow))
            {
                pow = pow + 1;
            }

            if (desiredMifSize < (int)Math.Pow(2, pow))
            {
                desiredMifSize = (int)Math.Pow(2, pow);
                fpx.Add(new FileParserException("MIF extended to a power of two length.", 0, 2));
            }

            if (memoryLocation < desiredMifSize - 1)
            {
                StringBuilder s = new StringBuilder();
                s.AppendFormat("[{0}..{1}] : 00000000;", String.Format("{0:X}", memoryLocation), String.Format("{0:X}", desiredMifSize - 1));
                outList.Add(s.ToString());
                memoryLocation = desiredMifSize;
            }
            else if (memoryLocation > desiredMifSize - 1)
            {
                while (desiredMifSize - 1 < memoryLocation)
                {
                    pow            = pow + 1;
                    desiredMifSize = (int)Math.Pow(2, pow);
                }

                if (memoryLocation == desiredMifSize - 1)
                {
                    StringBuilder s = new StringBuilder();
                    s.AppendFormat("{0} : 00000000;", String.Format(String.Format("{0:X}", desiredMifSize - 1)));
                    outList.Add(s.ToString());
                    memoryLocation = desiredMifSize;
                }
                else
                {
                    StringBuilder s = new StringBuilder();
                    s.AppendFormat("[{0}..{1}] : 00000000;", String.Format("{0:X}", memoryLocation), String.Format("{0:X}", desiredMifSize - 1));
                    outList.Add(s.ToString());
                    memoryLocation = desiredMifSize;
                }


                fpx.Add(new FileParserException("MIF extended to accommodate code length", 0, 2));
            }

            List <string> FileOutList = new List <string>();

            FileOutList.Add("WIDTH=32;");



            FileOutList.Add("DEPTH=" + Convert.ToString((int)Math.Pow(2, pow)) + ";");
            FileOutList.Add("ADDRESS_RADIX=HEX;");
            FileOutList.Add("DATA_RADIX=HEX;");
            FileOutList.Add("");
            FileOutList.Add("CONTENT BEGIN");
            FileOutList.AddRange(outList);
            FileOutList.Add("END;");

            return(FileOutList);
        }
Пример #2
0
        public SRCInstruction ParseInstruction(string inst)
        {
            SRCInstruction tmpInst = new SRCInstruction();

            tmpInst.originalInstructionString   = inst;
            tmpInst.outputInstructionString     = "";
            tmpInst.replaceImmediateWithAddress = false;

            string instruction = inst.ToLower();

            if (instruction == "nop")
            {
                tmpInst.outputInstructionString = "C8000000";
                return(tmpInst); //opcode for NOP
            }
            else if (instruction == "halt")
            {
                tmpInst.outputInstructionString = "D0000000"; //opcode for HALT!
                return(tmpInst);
            }
            else //not a single word no operand instruction
            {
                string[]      wsplit = inst.ToLower().Split(' ');
                StringBuilder s      = new StringBuilder();
                s.Append(opcodeDictionary[wsplit[0]]);

                try
                {
                    switch (wsplit[0])
                    {
                    case "ld":
                    case "ldi":
                    {
                        string regString;

                        if (wsplit.Length > 2)
                        {
                            regString = (wsplit[1] + wsplit[2]);

                            if (wsplit.Length > 3)
                            {
                                //dump warning
                            }
                        }
                        else
                        {
                            regString = wsplit[1];
                        }

                        Regex idx = new Regex(@"(([rR][0-9]*),\s*[$|0x|0X|-]*[0-9]+\(([rR][0-9]+)\))\s*");
                        Regex reg = new Regex(@"([rR][0-9]*),\s*[$|0x|0X|-]*[0-9]+\s*");
                        Regex sub = new Regex(@"([rR][0-9]*),\s*[\@][a-zA-Z0-9]+\s*");         //will match an @ declaration.... this should be good

                        if (idx.IsMatch(regString))
                        {
                            string[] dirString = regString.Split(',');
                            string[] addString = dirString[1].Split('(');

                            s.AppendFormat("{0}", RxToBin(FileParser.TrimWhiteSpace(dirString[0])));
                            s.AppendFormat("{0}", RxToBin(FileParser.TrimWhiteSpace(addString[1].TrimEnd(')'))));


                            string immString   = FileParser.TrimWhiteSpace(addString[0]);
                            int    c_sx        = 0;
                            string c_sx_string = "";

                            if (immString.StartsWith("$"))
                            {
                                immString = immString.Remove(0, 1);
                                c_sx      = Convert.ToInt32(immString, 16);
                            }
                            else if (immString.ToLower().StartsWith("0x"))
                            {
                                c_sx = Convert.ToInt32(immString, 16);
                            }
                            else
                            {
                                c_sx = Convert.ToInt32(immString);
                            }

                            if (c_sx < -524288 || c_sx > 524287)
                            {
                                throw new ArgumentOutOfRangeException("Immediate Value out of range.");
                            }
                            else
                            {
                                c_sx_string = String.Format(Convert.ToString(c_sx, 2)).PadLeft(19, '0');
                                if (c_sx_string.Length > 19)        //remove erroneous 1s
                                {
                                    c_sx_string = c_sx_string.Substring(c_sx_string.Length - 19, 19);
                                }
                            }

                            s.AppendFormat("{0}", c_sx_string);

                            tmpInst.outputInstructionString = Convert.ToUInt32(s.ToString(), 2).ToString("X");
                            return(tmpInst);
                        }
                        else if (reg.IsMatch(regString))
                        {
                            string[] dirString = regString.Split(',');
                            s.AppendFormat("{0}0000", RxToBin(FileParser.TrimWhiteSpace(dirString[0])));

                            string immString   = FileParser.TrimWhiteSpace(dirString[1]);
                            int    c_sx        = 0;
                            string c_sx_string = "";

                            if (immString.StartsWith("$"))
                            {
                                immString = immString.Remove(0, 1);
                                c_sx      = Convert.ToInt32(immString, 16);
                            }
                            else if (immString.ToLower().StartsWith("0x"))
                            {
                                c_sx = Convert.ToInt32(immString, 16);
                            }
                            else
                            {
                                c_sx = Convert.ToInt32(immString);
                            }

                            if (c_sx < -524288 || c_sx > 524287)
                            {
                                throw new ArgumentOutOfRangeException("Immediate Value out of range.");
                            }
                            else
                            {
                                c_sx_string = String.Format(Convert.ToString(c_sx, 2)).PadLeft(19, '0');
                                if (c_sx_string.Length > 19)         //remove erroneous 1s
                                {
                                    c_sx_string = c_sx_string.Substring(c_sx_string.Length - 19, 19);
                                }
                            }

                            s.AppendFormat("{0}", c_sx_string);

                            tmpInst.outputInstructionString = Convert.ToUInt32(s.ToString(), 2).ToString("X");
                            return(tmpInst);
                        }
                        else if (sub.IsMatch(regString))
                        {
                            //we're matching a subroutine. save this for later.
                            string[] dirString = regString.Split(',');
                            tmpInst.immediateToReplace          = dirString[1];
                            tmpInst.replaceImmediateWithAddress = true;
                            return(tmpInst);
                        }
                        else
                        {
                            throw new ArgumentException("Syntax Error in '" + inst + "' : invalid instruction format.");
                        }
                    }

                    case "st":
                    {
                        string regString;

                        if (wsplit.Length > 2)
                        {
                            regString = (wsplit[1] + wsplit[2]);

                            if (wsplit.Length > 3)
                            {
                                //dump warning
                            }
                        }
                        else
                        {
                            regString = wsplit[1];
                        }

                        Regex idx = new Regex(@"[$|0x|0X|-]([0-9]*[a-f|A-F]*)*\([rR][0-9]+\)\s*,\s*[rR][0-9]+");
                        Regex reg = new Regex(@"[$|0x|0X|-]*[0-9]+\s*,\s*[rR][0-9]+\s*");

                        if (idx.IsMatch(regString))
                        {
                            string[] dirString = regString.Split(',');
                            string[] addString = dirString[0].Split('(');

                            s.AppendFormat("{0}", RxToBin(FileParser.TrimWhiteSpace(dirString[1])));
                            s.AppendFormat("{0}", RxToBin(FileParser.TrimWhiteSpace(addString[1].TrimEnd(')'))));


                            string immString   = FileParser.TrimWhiteSpace(addString[0]);
                            int    c_sx        = 0;
                            string c_sx_string = "";

                            if (immString.StartsWith("$"))
                            {
                                immString = immString.Remove(0, 1);
                                c_sx      = Convert.ToInt32(immString, 16);
                            }
                            else if (immString.ToLower().StartsWith("0x"))
                            {
                                c_sx = Convert.ToInt32(immString, 16);
                            }
                            else
                            {
                                c_sx = Convert.ToInt32(immString);
                            }

                            if (c_sx < -524288 || c_sx > 524287)
                            {
                                throw new ArgumentOutOfRangeException("Immediate Value out of range.");
                            }
                            else
                            {
                                c_sx_string = String.Format(Convert.ToString(c_sx, 2)).PadLeft(19, '0');
                                if (c_sx_string.Length > 19)         //remove erroneous 1s
                                {
                                    c_sx_string = c_sx_string.Substring(c_sx_string.Length - 19, 19);
                                }
                            }

                            s.AppendFormat("{0}", c_sx_string);

                            tmpInst.outputInstructionString = Convert.ToUInt32(s.ToString(), 2).ToString("X");
                            return(tmpInst);
                        }
                        else if (reg.IsMatch(regString))
                        {
                            string[] dirString = regString.Split(',');
                            s.AppendFormat("{0}0000", RxToBin(FileParser.TrimWhiteSpace(dirString[1])));

                            string immString = FileParser.TrimWhiteSpace(dirString[0]);
                            int    c_sx      = 0;

                            string c_sx_string = "";

                            if (immString.StartsWith("$"))
                            {
                                immString = immString.Remove(0, 1);
                                c_sx      = Convert.ToInt32(immString, 16);
                            }
                            else if (immString.ToLower().StartsWith("0x"))
                            {
                                c_sx = Convert.ToInt32(immString, 16);
                            }
                            else
                            {
                                c_sx = Convert.ToInt32(immString);
                            }

                            if (c_sx < -524288 || c_sx > 524287)
                            {
                                throw new ArgumentOutOfRangeException("Immediate Value out of range.");
                            }
                            else
                            {
                                c_sx_string = String.Format(Convert.ToString(c_sx, 2)).PadLeft(19, '0');
                                if (c_sx_string.Length > 19)         //remove erroneous 1s
                                {
                                    c_sx_string = c_sx_string.Substring(c_sx_string.Length - 19, 19);
                                }
                            }

                            s.AppendFormat("{0}", c_sx_string);

                            tmpInst.outputInstructionString = Convert.ToUInt32(s.ToString(), 2).ToString("X");
                            return(tmpInst);
                        }
                        else
                        {
                            throw new ArgumentException("Syntax Error in '" + inst + "' : invalid instruction format.");
                        }
                    }


                    //operation,register instructions
                    case "jal":
                    case "jr":
                    case "mflo":
                    case "mfhi":
                    case "in":
                    case "out":
                    {
                        if (wsplit.Length > 2)
                        {
                            //dump warning here
                        }

                        s.Append(RxToBin(wsplit[1]));
                        tmpInst.outputInstructionString = Convert.ToUInt32(s.ToString().PadRight(32, '0'), 2).ToString("X");
                        return(tmpInst);
                    }

                    //operation, three registers, no immediate value
                    case "add":
                    case "sub":
                    case "and":
                    case "or":
                    case "shr":
                    case "shl":
                    case "ror":
                    case "rol":
                    {
                        string[] regString;

                        if (wsplit.Length > 3)
                        {
                            regString = (wsplit[1] + wsplit[2] + wsplit[3]).Split(',');

                            if (wsplit.Length > 4)
                            {
                                //dump warning
                            }
                        }
                        else if (wsplit.Length > 2)
                        {
                            regString = (wsplit[1] + wsplit[2]).Split(',');
                        }
                        else
                        {
                            regString = wsplit[1].Split(',');
                        }

                        s.AppendFormat("{0}{1}{2}", RxToBin(FileParser.TrimWhiteSpace(regString[0])), RxToBin(FileParser.TrimWhiteSpace(regString[1])), RxToBin(FileParser.TrimWhiteSpace(regString[2])));

                        tmpInst.outputInstructionString = Convert.ToUInt32(s.ToString().PadRight(32, '0'), 2).ToString("X");
                        return(tmpInst);
                    }

                    //operation, two registers, immediate value
                    case "addi":
                    case "andi":
                    case "ori":
                    {
                        string[] regString;

                        if (wsplit.Length > 3)
                        {
                            regString = (wsplit[1] + wsplit[2] + wsplit[3]).Split(',');

                            if (wsplit.Length > 4)
                            {
                                //dump warning
                            }
                        }
                        else if (wsplit.Length > 2)
                        {
                            regString = (wsplit[1] + wsplit[2]).Split(',');
                        }
                        else
                        {
                            regString = wsplit[1].Split(',');
                        }

                        s.AppendFormat("{0}{1}", RxToBin(FileParser.TrimWhiteSpace(regString[0])), RxToBin(FileParser.TrimWhiteSpace(regString[1])));

                        string immString = FileParser.TrimWhiteSpace(regString[2]);
                        int    c_sx      = 0;

                        string c_sx_string = "";

                        if (immString.StartsWith("$"))
                        {
                            immString = immString.Remove(0, 1);
                            c_sx      = Convert.ToInt32(immString, 16);
                        }
                        else if (immString.ToLower().StartsWith("0x"))
                        {
                            c_sx = Convert.ToInt32(immString, 16);
                        }
                        else
                        {
                            c_sx = Convert.ToInt32(immString);
                        }

                        if (c_sx < -524288 || c_sx > 524287)
                        {
                            throw new ArgumentOutOfRangeException("Immediate Value out of range.");
                        }
                        else
                        {
                            c_sx_string = String.Format(Convert.ToString(c_sx, 2)).PadLeft(19, '0');
                            if (c_sx_string.Length > 19)         //remove erroneous 1s
                            {
                                c_sx_string = c_sx_string.Substring(c_sx_string.Length - 19, 19);
                            }
                        }

                        s.AppendFormat("{0}", c_sx_string);

                        tmpInst.outputInstructionString = Convert.ToUInt32(s.ToString(), 2).ToString("X");
                        return(tmpInst);
                    }

                    //operation, two registers, nothing else
                    case "not":
                    case "neg":
                    case "div":
                    case "mul":
                    {
                        string[] regString;

                        if (wsplit.Length > 2)
                        {
                            regString = (wsplit[1] + wsplit[2]).Split(',');

                            if (wsplit.Length > 3)
                            {
                                //dump warning
                            }
                        }
                        else
                        {
                            regString = wsplit[1].Split(',');
                        }

                        s.AppendFormat("{0}{1}", RxToBin(FileParser.TrimWhiteSpace(regString[0])), RxToBin(FileParser.TrimWhiteSpace(regString[1])));

                        tmpInst.outputInstructionString = Convert.ToUInt32(s.ToString().PadRight(32, '0'), 2).ToString("X");
                        return(tmpInst);
                    }

                    //branches
                    case "brzr":
                    case "brnz":
                    case "brpl":
                    case "brmi":
                    {
                        string[] regString;

                        if (wsplit.Length > 2)
                        {
                            regString = (wsplit[1] + wsplit[2]).Split(',');

                            if (wsplit.Length > 3)
                            {
                                //dump warning
                            }
                        }
                        else
                        {
                            regString = wsplit[1].Split(',');
                        }

                        s.AppendFormat("{0}{1}", RxToBin(FileParser.TrimWhiteSpace(regString[0])), "00");

                        s.Append(branchSuffix[wsplit[0]]);


                        // Constant added to end
                        string immString = FileParser.TrimWhiteSpace(regString[1]);
                        int    c_sx      = 0;

                        string c_sx_string = "";

                        if (immString.StartsWith("$"))
                        {
                            immString = immString.Remove(0, 1);
                            c_sx      = Convert.ToInt32(immString, 16);
                        }
                        else if (immString.ToLower().StartsWith("0x"))
                        {
                            c_sx = Convert.ToInt32(immString, 16);
                        }
                        else
                        {
                            c_sx = Convert.ToInt32(immString);
                        }

                        if (c_sx < -524288 || c_sx > 524287)
                        {
                            throw new ArgumentOutOfRangeException("Immediate Value out of range.");
                        }
                        else
                        {
                            c_sx_string = String.Format(Convert.ToString(c_sx, 2)).PadLeft(19, '0');
                            if (c_sx_string.Length > 19)         //remove erroneous 1s
                            {
                                c_sx_string = c_sx_string.Substring(c_sx_string.Length - 19, 19);
                            }
                        }

                        s.AppendFormat("{0}", c_sx_string);



                        tmpInst.outputInstructionString = Convert.ToUInt32(s.ToString(), 2).ToString("X");
                        return(tmpInst);
                    }

                    default:
                    {
                        throw new ArgumentException("Unknown instruction: " + wsplit[0]);
                    }
                    }
                }
                catch (IndexOutOfRangeException)
                {
                    throw new ArgumentException("Syntax Error, argument(s) are missing from '" + inst + "'");
                }
            }
        }