Beispiel #1
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 #2
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 #3
0
        /// <summary>
        /// Generates a list of instructions for the ADDI instruction, given that the immediate argument
        /// is larger than 11 bits (neglecting the sign bit).
        /// </summary>
        /// <param name="address">The next address in the .text segment.</param>
        /// <param name="immediate"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        private List <int> GenerateExpandedInstruction(int address, int immediate, string[] args)
        {
            // load the upper 20 bits of the immediate into the destination register
            int shiftedImm = immediate >> 12;

            IEnumerable <int> backingLuiInstructions = new LuiProcessor().GenerateCodeForInstruction(address, new[] { args[0], shiftedImm.ToString() });

            // or that with the lower 12 bits of that immediate.
            IEnumerable <int> backingOriInstructions = new OriProcessor().GenerateCodeForInstruction(address, new[] { args[0], args[0], (immediate & 0xFFF).ToString() });

            // add the value of what we have in our register with the rs1 register.
            IEnumerable <int> backingAddInstructions = new AddProcessor().GenerateCodeForInstruction(address, new[] { args[0], args[0], args[1] });

            var instructionList = new List <int>();

            instructionList.AddRange(backingLuiInstructions);
            instructionList.AddRange(backingOriInstructions);
            instructionList.AddRange(backingAddInstructions);
            return(instructionList);
        }