public void Execute(string[] args)
 {
     try
     {
         if (IntExtensions.TryParseEx(args[0], out int address))
         {
             if (IntExtensions.TryParseEx(args[1], out int value))
             {
                 m_Proc.WriteMemory(address, value);
                 m_Terminal.PrintString("\t" + args[0] + " = " + args[1] + '\n');
             }
             else if (FloatExtensions.TryParseEx(args[1], out float fVal))
             {
                 m_Proc.WriteFloatToMemory(address, fVal);
                 m_Terminal.PrintString("\t" + args[0] + " = " + args[1] + '\n');
             }
             else
             {
                 m_Terminal.PrintString(args[1] + " was not a valid 32 bit value.\n");
             }
         }
         else
         {
             m_Terminal.PrintString(args[0] + " was not a valid 32 bit integer.\n");
         }
     }
     catch (Exception ex)
     {
         m_Terminal.PrintString(ex.Message + '\n');
     }
 }
        /// <summary>
        /// Parses an instruction and generates the binary code for it.
        /// </summary>
        /// <param name="address">The address of the instruction being parsed in the .text segment.</param>
        /// <param name="args">An array containing the arguments of the instruction.</param>
        /// <returns>One or more 32-bit integers representing this instruction. If this interface is implemented
        /// for a pseudo-instruction, this may return more than one instruction value.</returns>
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] args)
        {
            // we expect two arguments. if not, throw an ArgumentException
            if (args.Length != 2)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 2, received " + args.Length + '.');
            }

            string rs1          = args[0].Trim();
            string immediateStr = args[1].Trim();

            int immediate = 0;

            if (!IntExtensions.TryParseEx(immediateStr, out immediate))
            {
                throw new ArgumentException("auipc - argument 2 was non-integer immediate value.");
            }

            int rs1Reg = RegisterMap.GetNumericRegisterValue(rs1);

            // shift this such that
            int bitShiftedImm = immediate << 12;

            int instruction = 0;

            instruction |= bitShiftedImm;
            instruction |= (rs1Reg << 7);
            instruction |= 0x17;
            var inList = new List <int>();

            inList.Add(instruction);
            return(inList);
        }
Beispiel #3
0
            /// <summary>
            /// Takes an argument (e.g. 4(x9)) and parameterizes it into the offset component
            /// and its numeric register ID.
            /// </summary>
            /// <param name="trimmedArgToken">The token to parameterize, with whitespace trimmed on both left/right sides.</param>
            /// <returns>A parameterized register/offset structure.</returns>
            public static ParameterizedInstructionArg ParameterizeArgument(string trimmedArgToken)
            {
                string[] parameterizedArgs = trimmedArgToken.Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries).Apply((str) => str.Trim()).ToArray();

                // we should expect one or two arguments.
                if (parameterizedArgs.Length != 1 && parameterizedArgs.Length != 2)
                {
                    throw new ArgumentException(trimmedArgToken + " was not in a valid format.");
                }

                ParameterizedInstructionArg retVal = default(ParameterizedInstructionArg);

                // if we have one argument, assume its the register name, and that the offset is 0.
                if (parameterizedArgs.Length == 1)
                {
                    int registerId = RegisterMap.GetNumericRegisterValue(parameterizedArgs[0]);
                    retVal = new ParameterizedInstructionArg(0, registerId);
                }
                else
                {
                    bool isValidOffset = IntExtensions.TryParseEx(parameterizedArgs[0], out short offsetVal) && ((offsetVal & 0xF000) == 0);
                    if (!isValidOffset)
                    {
                        throw new ArgumentException(parameterizedArgs[0] + " is not a valid 12-bit offset.");
                    }

                    int registerId = RegisterMap.GetNumericRegisterValue(parameterizedArgs[1]);
                    retVal = new ParameterizedInstructionArg(offsetVal, registerId);
                }

                return(retVal);
            }
Beispiel #4
0
        public void Execute(string[] args)
        {
            try
            {
                string fmtString = args[1];

                if (fmtString.Contains("\""))
                {
                    fmtString = fmtString.Replace("\"", string.Empty);
                }

                fmtString = fmtString.Trim();

                if (IntExtensions.TryParseEx(args[0], out int iValue))
                {
                    int readData = m_Proc.ReadMemory(iValue);
                    m_Terminal.PrintString("\t" + args[0] + " = " + readData.ToString(fmtString) + '\n');
                }
                else
                {
                    m_Terminal.PrintString(args[0] + " was not a valid 32 bit integer.\n");
                }
            }
            catch (Exception ex)
            {
                m_Terminal.PrintString(ex.Message + '\n');
            }
        }
        /// <summary>
        /// Adds a half element to the object file.
        /// </summary>
        /// <param name="objFile">The object file to add to.</param>
        /// <param name="fullText">The full text of the assembly line.</param>
        /// <param name="declarationToken">The token specifying the declaration of the size parameter.</param>
        private void AddShortElementToFile(BasicObjectFile objFile, string fullText, string declarationToken)
        {
            // find the token directly after the size directive
            int    substrBeginIdx = fullText.IndexOf(declarationToken) + declarationToken.Length;
            string arguments      = fullText.Substring(substrBeginIdx);

            // split by commas.
            string[] tokenizedArgs = arguments.Split(new[] { ',' });
            tokenizedArgs = tokenizedArgs.Apply((str) => str.Trim()).ToArray();

            // iterate through each element in the "array".
            foreach (string token in tokenizedArgs)
            {
                // if it contains a ':' character, then this itself is an array of the initialized token.
                if (token.Contains(':'))
                {
                    string[] subtokens = token.Split(new[] { ':' }).Apply((str) => str.Trim()).ToArray();
                    if (subtokens.Length == 2)
                    {
                        int numElems = int.Parse(subtokens[1]);

                        // this syntax is wonky; we're trying to parse literal char elements
                        // as well as normal bytes here.
                        if (!IntExtensions.TryParseEx(subtokens[0], out short elemToAdd))
                        {
                            // see if we can resolve the string as a symbol.
                            Symbol sym = m_SymTbl.GetSymbol(subtokens[0]);
                            elemToAdd = (short)sym.Address;
                        }
                        for (int i = 0; i < numElems; ++i)
                        {
                            objFile.AddDataElement(elemToAdd);
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Expected size parameter after ':' token.");
                    }
                }
                else
                {
                    // otherwise, it should just be an element (without any size modifiers).
                    // just parse it and add it.
                    if (!IntExtensions.TryParseEx(token, out short elemToAdd))
                    {
                        // see if we can resolve the string as a symbol.
                        Symbol sym = m_SymTbl.GetSymbol(token);
                        elemToAdd = (short)sym.Address;
                    }

                    objFile.AddDataElement(elemToAdd);
                }
            }
        }
        /// <summary>
        /// Parses an instruction and generates the binary code for it.
        /// </summary>
        /// <param name="address">The address of the instruction being parsed in the .text segment.</param>
        /// <param name="args">An array containing the arguments of the instruction.</param>
        /// <returns>One or more 32-bit integers representing this instruction. If this interface is implemented
        /// for a pseudo-instruction, this may return more than one instruction value.</returns>
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] args)
        {
            // we expect three arguments. if not, throw an ArgumentException
            if (args.Length != 3)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 3, received " + args.Length + '.');
            }

            string rd  = args[0].Trim();
            string rs1 = args[1].Trim();
            string rs2 = args[2].Trim();

            IEnumerable <int> returnVal = null;
            int instruction             = 0;
            int rdReg  = RegisterMap.GetNumericRegisterValue(rd);
            int rs1Reg = RegisterMap.GetNumericRegisterValue(rs1);
            int rs2Reg = 0;

            try
            {
                rs2Reg = RegisterMap.GetNumericRegisterValue(rs2);

                List <int> instructionList = new List <int>();
                instruction |= (rs2Reg << 20);
                instruction |= (rs1Reg << 15);
                instruction |= (0x7 << 12);
                instruction |= (rdReg << 7);
                instruction |= 0x33;
                instructionList.Add(instruction);
                returnVal = instructionList;
            }
            catch (ArgumentException)
            {
                // try to parse the string as a number; maybe the user meant andi?
                short immediate = 0;
                bool  isShort   = IntExtensions.TryParseEx(rs2, out immediate);
                if (isShort)
                {
                    var immediateParser = new AndiProcessor();
                    returnVal = immediateParser.GenerateCodeForInstruction(address, args);
                }
                else
                {
                    // otherwise, this is garbage; rethrow the value.
                    throw;
                }
            }

            return(returnVal);
        }
Beispiel #7
0
        /// <summary>
        /// Parses an instruction and generates the binary code for it.
        /// </summary>
        /// <param name="address">The address of the instruction being parsed in the .text segment.</param>
        /// <param name="args">An array containing the arguments of the instruction.</param>
        /// <returns>One or more 32-bit integers representing this instruction. If this interface is implemented
        /// for a pseudo-instruction, this may return more than one instruction value.</returns>
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] args)
        {
            // we expect three arguments. if not, throw an ArgumentException
            if (args.Length != 3)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 3, received " + args.Length + '.');
            }

            IEnumerable <int> returnVal = null;
            int  rdReg            = RegisterMap.GetNumericRegisterValue(args[0]);
            int  rs1Reg           = RegisterMap.GetNumericRegisterValue(args[1]);
            int  shiftAmt         = 0;
            bool isValidImmediate = IntExtensions.TryParseEx(args[2], out shiftAmt);

            // ensure our shift amount is 5 bits or less.
            isValidImmediate = isValidImmediate && ((shiftAmt & 0xFFFFFFE0) == 0);
            var instructionList = new List <int>();

            if (isValidImmediate)
            {
                int instruction = 0;
                instruction |= (0x1 << 30);
                instruction |= (shiftAmt << 20);
                instruction |= (rs1Reg << 15);
                instruction |= (0x5 << 12);
                instruction |= (rdReg << 7);
                instruction |= 0x13;
                instructionList.Add(instruction);
                returnVal = instructionList;
            }
            else
            {
                // otherwise, emit three instructions. load the upper 20 bits of the immediate into the destination register,
                // bitwise-or it with the remaining 12 bits, and then shift the target register by the destination register.
                var luiProc = new LuiProcessor();
                instructionList.AddRange(luiProc.GenerateCodeForInstruction(address, new string[] { args[0], (shiftAmt >> 12).ToString() }));

                int orImmVal = shiftAmt & 0xFFF;
                var oriProc  = new OriProcessor();
                instructionList.AddRange(oriProc.GenerateCodeForInstruction(address, new string[] { args[0], orImmVal.ToString() }));

                var sraProc = new SraProcessor();
                instructionList.AddRange(sraProc.GenerateCodeForInstruction(address, new string[] { args[0], args[1], args[0] }));
            }

            return(returnVal);
        }
Beispiel #8
0
        /// <summary>
        /// Parses an instruction and generates the binary code for it.
        /// </summary>
        /// <param name="address">The address of the instruction being parsed in the .text segment.</param>
        /// <param name="args">An array containing the arguments of the instruction.</param>
        /// <returns>One or more 32-bit integers representing this instruction. If this interface is implemented
        /// for a pseudo-instruction, this may return more than one instruction value.</returns>
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] args)
        {
            if (args.Length != 3)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 3, received " + args.Length + '.');
            }

            IEnumerable <int> returnVal = null;
            int instruction             = 0;
            int rdReg  = RegisterMap.GetNumericRegisterValue(args[0]);
            int rs1Reg = RegisterMap.GetNumericRegisterValue(args[1]);
            int rs2Reg = 0;

            try
            {
                rs2Reg = RegisterMap.GetNumericRegisterValue(args[2]);

                List <int> instructionList = new List <int>();
                instruction |= (rs2Reg << 20);
                instruction |= (rs1Reg << 15);

                // or opcode/funt3/funct7 = 0x33/0x6/0x0
                instruction |= (0x6 << 12);
                instruction |= (rdReg << 7);
                instruction |= 0x33;
                instructionList.Add(instruction);
                returnVal = instructionList;
            }
            catch (ArgumentException)
            {
                // try parsing as ori instruction
                int  immediate = 0;
                bool isShort   = IntExtensions.TryParseEx(args[2], out immediate);
                if (isShort)
                {
                    var immediateParser = new OriProcessor();
                    returnVal = immediateParser.GenerateCodeForInstruction(address, args);
                }
                else
                {
                    throw;
                }
            }

            return(returnVal);
        }
        public void Execute(string[] args)
        {
            if (!IntExtensions.TryParseEx(args[0], out int pgmCounter))
            {
                // if the argument was not a program counter arg, try to find the source line.
                string srcData = args[0];

                string[] splitData = srcData.Split(':');
                if (splitData.Length == 2)
                {
                    for (int i = 0; i < 2; ++i)
                    {
                        splitData[i] = splitData[i].Trim();
                    }

                    int srcLineNum = int.Parse(splitData[1]);

                    bool found = false;
                    foreach (var srcLine in m_SrcData.Values)
                    {
                        if (srcLine.SourceFilePath == splitData[0] && srcLine.SourceLineNumber == srcLineNum)
                        {
                            pgmCounter = srcLine.ProgramCounterLocation;
                            found      = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        m_Terminal.PrintString("Could not attach breakpoint to line " + srcLineNum + " of file " + splitData[0] + '\n');
                    }
                }
            }

            if (m_SrcData.ContainsKey(pgmCounter))
            {
                m_Exec.SetBreakpoint(pgmCounter);
                m_Terminal.PrintString("Successfully attached breakpoint to source address 0x" + pgmCounter.ToString("x8") + '\n');
            }
            else
            {
                m_Terminal.PrintString("Could not attach breakpoint to given source address.\n");
            }
        }
 public void Execute(string[] args)
 {
     try
     {
         if (IntExtensions.TryParseEx(args[0], out int iValue))
         {
             int readData = m_Proc.ReadMemory(iValue);
             m_Terminal.PrintString("\t" + args[0] + " = " + readData + '\n');
         }
         else
         {
             m_Terminal.PrintString(args[0] + " was not a valid 32 bit integer.\n");
         }
     }
     catch (Exception ex)
     {
         m_Terminal.PrintString(ex.Message + '\n');
     }
 }
Beispiel #11
0
        /// <summary>
        /// Parses an instruction and generates the binary code for it.
        /// </summary>
        /// <param name="address">The address of the instruction being parsed in the .text segment.</param>
        /// <param name="args">An array containing the arguments of the instruction.</param>
        /// <returns>One or more 32-bit integers representing this instruction. If this interface is implemented
        /// for a pseudo-instruction, this may return more than one instruction value.</returns>
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] args)
        {
            // we expect three arguments. if not, throw an ArgumentException
            if (args.Length != 3)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 3, received " + args.Length + '.');
            }


            int rdReg  = RegisterMap.GetNumericRegisterValue(args[0]);
            int rs1Reg = RegisterMap.GetNumericRegisterValue(args[1]);

            uint immVal           = 0;
            bool isValidImmediate = IntExtensions.TryParseEx(args[2], out immVal);

            // this is okay, as we expect an unsigned value.
            isValidImmediate = isValidImmediate && ((immVal & 0xFFFFF000) == 0);

            var instructionList = new List <int>();

            if (isValidImmediate)
            {
                int instruction = GenerateUnexpandedInstruction(immVal, rs1Reg, rdReg);
                instructionList.Add(instruction);
            }
            else
            {
                // otherwise, emit three instructions. load the upper 20 bits of the immediate into the destination register,
                // bitwise-or it with the remaining 12 bits, and then use sltu (the s-type).
                var luiProc = new LuiProcessor();
                instructionList.AddRange(luiProc.GenerateCodeForInstruction(address, new string[] { args[0], (immVal >> 12).ToString() }));

                uint orImmVal = immVal & 0xFFF;
                var  oriProc  = new OriProcessor();
                instructionList.AddRange(oriProc.GenerateCodeForInstruction(address, new string[] { args[0], orImmVal.ToString() }));

                var sltuProc = new SltuProcessor();
                instructionList.AddRange(sltuProc.GenerateCodeForInstruction(address, new string[] { args[0], args[1], args[0] }));
            }

            return(instructionList);
        }
Beispiel #12
0
 public void Execute(string[] args)
 {
     try
     {
         string regName = args[0];
         if (IntExtensions.TryParseEx(args[1], out int iValue))
         {
             if (RegisterMap.IsNamedIntegerRegister(regName))
             {
                 int regIdx = RegisterMap.GetNumericRegisterValue(regName);
                 m_Registers.UserIntRegisters[regIdx].Value = iValue;
                 m_Terminal.PrintString("\t" + regName + " = " + iValue + '\n');
             }
             else
             {
                 throw new ParseException(regName + " was not a valid register name.");
             }
         }
         else if (FloatExtensions.TryParseEx(args[1], out float fValue))
         {
             if (RegisterMap.IsNamedFloatingPointRegister(regName))
             {
                 int regIdx = RegisterMap.GetNumericFloatingPointRegisterValue(regName);
                 m_Registers.UserFloatingPointRegisters[regIdx].Value = fValue;
                 m_Terminal.PrintString("\t" + regName + " = " + fValue + '\n');
             }
             else
             {
                 throw new ParseException(regName + " was not a valid register name.");
             }
         }
         else
         {
             throw new ParseException(args[1] + " was not a valid 32-bit value");
         }
     }
     catch (Exception ex)
     {
         m_Terminal.PrintString(ex.Message + '\n');
     }
 }
Beispiel #13
0
        /// <summary>
        /// Parses an instruction and generates the binary code for it.
        /// </summary>
        /// <param name="address">The address of the instruction being parsed in the .text segment.</param>
        /// <param name="args">An array containing the arguments of the instruction.</param>
        /// <returns>One or more 32-bit integers representing this instruction. If this interface is implemented
        /// for a pseudo-instruction, this may return more than one instruction value.</returns>
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] args)
        {
            // we expect three arguments. if not, throw an ArgumentException
            if (args.Length != 3)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 3, received " + args.Length + '.');
            }

            int  rdReg            = RegisterMap.GetNumericRegisterValue(args[0]);
            int  rs1Reg           = RegisterMap.GetNumericRegisterValue(args[1]);
            int  immVal           = 0;
            bool isValidImmediate = IntExtensions.TryParseEx(args[2], out immVal);

            if (isValidImmediate)
            {
                var instructionList = new List <int>();

                // if the immediate is greater than 12 bits, use
                // an auipc instruction.
                if (!IsValidTwelveBitSignedImmediate(immVal))
                {
                    var auipcHelper = new AuipcProcessor();
                    IEnumerable <int> auipcInstructions =
                        auipcHelper.GenerateCodeForInstruction(address, new string[] { args[1], (immVal >> 12).ToString() });
                    instructionList.AddRange(auipcInstructions);
                }

                int instruction = 0;
                instruction |= (immVal << 20);
                instruction |= (rs1Reg << 15);
                instruction |= (rdReg << 7);
                instruction |= 0x67;
                instructionList.Add(instruction);

                return(instructionList);
            }
            else
            {
                throw new ArgumentException("Immediate was not a valid 32-bit integer.");
            }
        }
Beispiel #14
0
        /// <summary>
        /// Parses an instruction and generates the binary code for it.
        /// </summary>
        /// <param name="address">The address of the instruction being parsed in the .text segment.</param>
        /// <param name="args">An array containing the arguments of the instruction.</param>
        /// <returns>One or more 32-bit integers representing this instruction. If this interface is implemented
        /// for a pseudo-instruction, this may return more than one instruction value.</returns>
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] args)
        {
            // we expect three arguments. if not, throw an ArgumentException
            if (args.Length != 3)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 3, received " + args.Length + '.');
            }

            int  rdReg            = RegisterMap.GetNumericRegisterValue(args[0]);
            int  rs1Reg           = RegisterMap.GetNumericRegisterValue(args[1]);
            int  immVal           = 0;
            bool isValidImmediate = IntExtensions.TryParseEx(args[2], out immVal);

            if (isValidImmediate)
            {
                var instructionList = default(List <int>);

                // see if this is a valid 12 bit immediate.
                // if it is greater, treat this as a pseudo instruction and generate
                // underlying code to support it. otherwise, use the real andi instruction.
                if (!IsValidTwelveBitSignedImmediate(immVal))
                {
                    instructionList = GenerateExpandedInstruction(address, immVal, args);
                }
                else
                {
                    instructionList = new List <int>();
                    int instruction = GenerateUnexpandedInstruction(immVal, rs1Reg, rdReg);
                    instructionList.Add(instruction);
                }

                return(instructionList);
            }
            else
            {
                throw new ArgumentException(args[2] + " is not a valid immediate value.");
            }
        }
Beispiel #15
0
        /// <summary>
        /// Parses an instruction and generates the binary code for it.
        /// </summary>
        /// <param name="address">The address of the instruction being parsed in the .text segment.</param>
        /// <param name="args">An array containing the arguments of the instruction.</param>
        /// <returns>One or more 32-bit integers representing this instruction. If this interface is implemented
        /// for a pseudo-instruction, this may return more than one instruction value.</returns>
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] args)
        {
            // we expect three arguments. if not, throw an ArgumentException
            if (args.Length != 3)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 3, received " + args.Length + '.');
            }

            int rdReg  = RegisterMap.GetNumericRegisterValue(args[0]);
            int rs1Reg = RegisterMap.GetNumericRegisterValue(args[1]);

            int  immVal           = 0;
            bool isValidImmediate = IntExtensions.TryParseEx(args[2], out immVal);

            if (isValidImmediate)
            {
                var instructionList = default(List <int>);

                // if the mask is greater not zero, this would indicate that there are bits beyond the 11th bit offset.
                // help the user by generating equivalent s-type instructions
                if (!IsValidTwelveBitSignedImmediate(immVal))
                {
                    instructionList = GenerateExpandedInstruction(address, immVal, args);
                }
                else
                {
                    instructionList = new List <int>();
                    int instruction = GenerateUnexpandedInstruction(immVal, rs1Reg, rdReg);
                    instructionList.Add(instruction);
                }

                return(instructionList);
            }
            else
            {
                throw new ArgumentException(args[2] + " is not a valid immediate value.");
            }
        }
        /// <summary>
        /// Adds a byte element to the object file.
        /// </summary>
        /// <param name="objFile">The object file to add to.</param>
        /// <param name="fullText">The full text of the assembly line.</param>
        /// <param name="declarationToken">The token specifying the declaration of the size parameter.</param>
        private void AddByteElementToFile(BasicObjectFile objFile, string fullText, string declarationToken)
        {
            // find the token directly after the size directive
            int    substrBeginIdx = fullText.IndexOf(declarationToken) + declarationToken.Length;
            string arguments      = fullText.Substring(substrBeginIdx);

            // split by commas.
            string[] tokenizedArgs = arguments.Split(new[] { ',' });
            tokenizedArgs = tokenizedArgs.Apply((str) => str.Trim()).ToArray();

            // iterate through each element in the "array".
            foreach (string token in tokenizedArgs)
            {
                // if it contains a ':' character, then this itself is an array of the initialized token.
                if (token.Contains(':'))
                {
                    string[] subtokens = token.Split(new[] { ':' }).Apply((str) => str.Trim()).ToArray();
                    if (subtokens.Length == 2)
                    {
                        int numElems = int.Parse(subtokens[1]);

                        // first, try to get the value as a byte.
                        if (!IntExtensions.TryParseEx(subtokens[0], out byte byteElem))
                        {
                            // if we fail, then try parsing the character as a literal.
                            if (!StringUtils.TryParseCharacterLiteralAsByte(subtokens[0], out byteElem))
                            {
                                // as a fallback, see if we can resolve the string as a symbol.
                                Symbol sym = m_SymTbl.GetSymbol(subtokens[0]);
                                byteElem = (byte)sym.Address;
                            }
                        }

                        for (int i = 0; i < numElems; ++i)
                        {
                            objFile.AddDataElement(byteElem);
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Expected size parameter after ':' token.");
                    }
                }
                else
                {
                    // otherwise, it should just be an element (without any size modifiers).
                    // just parse it and add it.
                    // first, try to get the value as a byte.
                    if (!IntExtensions.TryParseEx(token, out byte byteElem))
                    {
                        // if we fail, then try parsing the character as a literal.
                        if (!StringUtils.TryParseCharacterLiteralAsByte(token, out byteElem))
                        {
                            // as a fallback, see if we can resolve the string as a symbol.
                            Symbol sym = m_SymTbl.GetSymbol(token);
                            byteElem = (byte)sym.Address;
                        }
                    }

                    objFile.AddDataElement(byteElem);
                }
            }
        }
Beispiel #17
0
        /// <summary>
        /// Parses an instruction and generates the binary code for it.
        /// </summary>
        /// <param name="address">The address of the instruction being parsed in the .text segment.</param>
        /// <param name="args">An array containing the arguments of the instruction.</param>
        /// <returns>One or more 32-bit integers representing this instruction. If this interface is implemented
        /// for a pseudo-instruction, this may return more than one instruction value.</returns>
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] args)
        {
            // we expect two arguments. if not, throw an ArgumentException
            if (args.Length != 2)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 2, received " + args.Length + '.');
            }

            int rdReg = RegisterMap.GetNumericRegisterValue(args[0]);

#if DEBUG
            int targetAddress = 0;

            if (SymbolTable.ContainsSymbol(args[1]))
            {
                Symbol symbolLabel = SymbolTable.GetSymbol(args[1]);
                targetAddress = symbolLabel.Address;
            }
            else if (!IntExtensions.TryParseEx(args[1], out targetAddress))
            {
                throw new ArgumentException(args[1] + " was not a symbol name or valid 32-bit address.");
            }
            var instructionList = new List <int>();

            // the offset is doubled implicitly by the processor, so halve it here.
            int offset = (targetAddress - address);

            // this should rarely happen, but if the halved immediate exceeds the 21 bit boundary,
            // error out and notify the user.
            if ((Math.Abs(offset / 2) & 0xFFE00000) != 0)
            {
                throw new ArgumentException("jal - the offset between the address of \"0x" + targetAddress.ToString("X") + "\"" +
                                            " and this instruction address (0x" +
                                            address.ToString("X") + ") exceeds the 21 bit immediate limit. Use jalr instead.");
            }
#else
            Symbol symbolLabel     = SymbolTable.GetSymbol(args[1]);
            var    instructionList = new List <int>();

            // the offset is doubled implicitly by the processor, so halve it here.
            int offset = (symbolLabel.Address - address);

            // this should rarely happen, but if the halved immediate exceeds the 21 bit boundary,
            // error out and notify the user.
            if ((Math.Abs(offset / 2) & 0xFFE00000) != 0)
            {
                throw new ArgumentException("jal - the offset between the address of \"" + symbolLabel.LabelName + "\"" +
                                            " (0x" + symbolLabel.Address.ToString("X") + " and this instruction address (0x" +
                                            address.ToString("X") + ") exceeds the 21 bit immediate limit. Use jalr instead.");
            }
#endif

            int instruction = 0;

            // get the twentieth bit offset (21st bit) of the offset value
            // and shift it to the 31st bit offset.
            instruction |= ((offset & 0x100000) << 11);

            // get the 10-1 bit offsets and shift that range to the 30-20 offset.
            instruction |= ((offset & 0x7FE) << 20);

            // get the 11th bit offset and shift it to offset 20.
            instruction |= ((offset & 0x800) << 9);

            // get the 19-12 bit offsets and shift them to position 18-11
            instruction |= ((offset & 0xFF000));

            // shift the rd register value up to offset 11-7
            instruction |= (rdReg << 7);

            instruction |= 0x6F;
            instructionList.Add(instruction);

            return(instructionList);
        }