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); }
/// <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); }
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); }
/// <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); }
/// <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'); } }
/// <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); }
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'); } }
/// <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) { // 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."); } }
/// <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); } } }
/// <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); }