/// <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 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 |= 0x2000000;
                instruction |= (rs2Reg << 20);
                instruction |= (rs1Reg << 15);
                instruction |= (0x6 << 12);
                instruction |= (rdReg << 7);
                instruction |= 0x33;
                instructionList.Add(instruction);
                returnVal = instructionList;
            }
            catch (ArgumentException)
            {
                throw;
            }

            return(returnVal);
        }
Пример #2
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);
            }
Пример #3
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 nextTextAddress, string[] args)
        {
            if (args.Length != 2)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 2, received " + args.Length + '.');
            }

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

            var retList = new List <int>();
            ParameterizedInstructionArg arg = ParameterizedInstructionArg.ParameterizeArgument(args[1]);
            int instruction = 0;
            int upperOffset = (arg.Offset & 0xFE0);
            int lowerOffset = (arg.Offset & 0x1F);

            instruction |= (upperOffset << 25);
            instruction |= (rs2 << 20);
            instruction |= (arg.Register << 15);

            byte funcCode = GetFunctionCode();

            instruction |= (funcCode << 12);

            instruction |= (lowerOffset << 7);
            instruction |= 0x23;
            retList.Add(instruction);

            return(retList);
        }
Пример #4
0
 public void Execute(string[] args)
 {
     try
     {
         int    regIdx  = -1;
         string regName = args[0];
         if (RegisterMap.IsNamedIntegerRegister(regName))
         {
             regIdx = RegisterMap.GetNumericRegisterValue(regName);
             m_Terminal.PrintString("\t" + regName + " = " + m_Registers.UserIntRegisters[regIdx].Value + '\n');
         }
         else if (RegisterMap.IsNamedFloatingPointRegister(regName))
         {
             regIdx = RegisterMap.GetNumericFloatingPointRegisterValue(regName);
             m_Terminal.PrintString("\t" + regName + " = " + m_Registers.UserFloatingPointRegisters[regIdx].Value + '\n');
         }
         else
         {
             throw new ParseException(regName + " is not a valid integer register name.");
         }
     }
     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);
        }
        /// <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);
        }
Пример #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);
        }
Пример #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);
        }
Пример #9
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);
        }
Пример #10
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.");
            }
        }
        /// <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 != 2)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 2, received " + args.Length + '.');
            }

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

            var retList = new List <int>();

            byte funcCode = GetFunctionCode();

            if (IsParameterizedToken(args[1]))
            {
                ParameterizedInstructionArg arg = ParameterizedInstructionArg.ParameterizeArgument(args[1]);
                int instruction = 0;
                instruction |= ((arg.Offset & 0xFFF) << 20);
                instruction |= (arg.Register << 15);
                instruction |= (funcCode << 12);
                instruction |= (rdReg << 7);
                instruction |= 0x3;
                retList.Add(instruction);
            }
            else
            {
                Symbol sym            = SymbolTable.GetSymbol(args[1]);
                int    shiftedAddress = sym.Address >> 12;
                retList.AddRange(new LuiProcessor().GenerateCodeForInstruction(address, new[] { args[0], shiftedAddress.ToString() }));
                int numericOffset = sym.Address & 0xFFF;
                int instruction   = 0;
                instruction |= (numericOffset << 20);
                instruction |= (rdReg << 15);
                instruction |= (funcCode << 12);
                instruction |= (rdReg << 7);
                instruction |= 0x3;
                retList.Add(instruction);
            }

            return(retList);
        }
Пример #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');
     }
 }
        public override IEnumerable <int> GenerateCodeForInstruction(int address, string[] instructionArgs)
        {
            // we expect three arguments. if not, throw an ArgumentException
            if (instructionArgs.Length != 2)
            {
                throw new ArgumentException("Invalid number of arguments provided. Expected 2, received " + instructionArgs.Length + '.');
            }

            const int BASE_OPCODE = 0x53;

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

            int outputInst = (0x1A << 27) | (rs1Reg << 15) | (rdReg << 7) | BASE_OPCODE;

            var instList = new List <int> {
                outputInst
            };

            return(instList);
        }
        public void Execute(string[] args)
        {
            try
            {
                string fmtString = args[1];

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

                fmtString = fmtString.Trim();

                int    regIdx  = -1;
                string regName = string.Empty;
                if (RegisterMap.IsNamedIntegerRegister(args[0]))
                {
                    regIdx  = RegisterMap.GetNumericRegisterValue(args[0]);
                    regName = args[0];
                    m_Terminal.PrintString("\t" + regName + " = " +
                                           m_Registers.UserIntRegisters[regIdx].Value.ToString(fmtString) + '\n');
                }
                else if (RegisterMap.IsNamedFloatingPointRegister(args[0]))
                {
                    regIdx  = RegisterMap.GetNumericFloatingPointRegisterValue(args[0]);
                    regName = args[0];
                    m_Terminal.PrintString("\t" + regName + " = " +
                                           m_Registers.UserFloatingPointRegisters[regIdx].Value.ToString(fmtString) + '\n');
                }
                else
                {
                    throw new ParseException(regIdx + " was not a valid register name.");
                }
            }
            catch (Exception ex)
            {
                m_Terminal.PrintString(ex.Message + '\n');
            }
        }
Пример #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>);

                // 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.");
            }
        }
Пример #16
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.");
            }
        }
Пример #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);
        }
        /// <summary>
        /// Generates the basic code for a branch instruction by delegating to implementing classes
        /// to provide a function code.
        /// </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 rs1Reg = RegisterMap.GetNumericRegisterValue(args[0]);
            int rs2Reg = RegisterMap.GetNumericRegisterValue(args[1]);

            Symbol symbolLabel = SymbolTable.GetSymbol(args[2]);

            // the instruction should always have a last two bits of 0, since they're word aligned.
            System.Diagnostics.Debug.Assert((symbolLabel.Address & 0x3) == 0);

            // find the difference between the jump-to address and the theoretical next address.
            // note that the processor internally doubles this value, so we halve it here.
            int offset = (symbolLabel.Address - address);

            // if the offset is greater than the 12 bit immediate,
            // throw an error so that bad code isn't silently generated.
            if (!IsValidTwelveBitSignedImmediate(Math.Abs(offset)))
            {
                throw new ArgumentException("The offset between the address of \"" + symbolLabel.LabelName + "\"" +
                                            " (0x" + symbolLabel.Address.ToString("X") + " and this instruction address (0x" +
                                            address.ToString("X") + ") exceeds the 12 bit immediate limit.");
            }

            // this is a B-type instruction, so bits go all over the place.
            // last bit is ignored, since it would be zero anyway.

            // get the thirteenth (offset 12) bit of the immediate (counting from zero), and shift it to the end.
            int offset0     = offset & 0x1000;
            int instruction = 0;

            instruction |= (offset0 << 19);

            // get the 11-6 (offsets 10-5) bits of the immediate.
            int offset1 = offset & 0x7E0;

            instruction |= (offset1 << 20);

            instruction |= (rs2Reg << 20);
            instruction |= (rs1Reg << 15);

            // Get the implementation function code, and move it into position
            byte funcCode = GetFunctionCode();

            instruction |= (funcCode << 12);

            // get the 5-2 (offsets 4-1) bits of the immediate
            // they belong in the 11-8th offset of the code, so left shift by 7 bits.
            int offset2 = offset & 0x1E;

            instruction |= (offset2 << 7);

            // get the 12th (offset 11) bit of the immediate.
            // this belongs in the 7th offset, so we need to bit shift it right by 4.
            int offset3 = offset & 0x800;

            instruction |= (offset3 >> 4);
            instruction |= 0x63;

            var instructionList = new List <int>();

            instructionList.Add(instruction);
            return(instructionList);
        }