private ASMSingleEncodeResult EncodeASMSingle(string[] parts, EncodingFormat encoding, uint pc, bool littleEndian) { // Initialize variables //string binary = ""; //string hex = ""; string strArgs = ""; string[] args = null; /* * if (!string.IsNullOrEmpty(parts[1])) * { * strArgs = ASMStringHelper.RemoveSpaces(parts[1]).Replace('(',',').Replace(")",""); * args = strArgs.Split(','); * } */ // Find encoding format and syntax string command = parts[0].ToLower(); EncodingFormat encodingFormat = FormatHelper.FindFormatByCommand(command); string formatBinary = encodingFormat.Binary; string syntax = encodingFormat.Syntax; string newFormat = formatBinary; if (!string.IsNullOrEmpty(parts[1])) { List <string> argsList = new List <string>(); strArgs = ASMStringHelper.RemoveSpaces(parts[1]); bool foundArg = false; int strArgCharIndex = 0; foreach (char currentChar in syntax) { if (Char.IsLetter(currentChar)) { foundArg = true; } else if (foundArg) { foundArg = false; bool isHiLo = ((strArgs.IndexOf("%hi(", strArgCharIndex) == strArgCharIndex) || (strArgs.IndexOf("%lo(", strArgCharIndex) == strArgCharIndex)); int separatorIndex = strArgs.IndexOf(currentChar, strArgCharIndex + (isHiLo ? 4 : 0)); argsList.Add(strArgs.Substring(strArgCharIndex, separatorIndex - strArgCharIndex)); strArgCharIndex = separatorIndex + 1; } } if (foundArg) { argsList.Add(strArgs.Substring(strArgCharIndex, strArgs.Length - strArgCharIndex)); } args = argsList.ToArray(); } // Create array for registers and immediates Nullable <uint>[] regValue = new Nullable <uint> [26]; Nullable <uint>[][] partialRegValue = new Nullable <uint> [26][]; uint[] immedValue = new uint[26]; int argsIndex = 0; int regIndex = 0; int immedIndex = 0; // Fill arrays based on order of arguments (syntax) foreach (char elementTypeChar in syntax) { bool incrementArgsIndex = true; switch (elementTypeChar) { case ASMElementTypeCharacter.GPRegister: regValue[regIndex++] = EncodeGPRegister(args[argsIndex]); break; case ASMElementTypeCharacter.GenericRegister: regValue[regIndex++] = EncodeGenericRegister(args[argsIndex]); break; case ASMElementTypeCharacter.FloatRegister: regValue[regIndex++] = EncodeFloatRegister(args[argsIndex]); break; case ASMElementTypeCharacter.VFPURegister: regValue[regIndex] = EncodeVFPURegister(args[argsIndex], encodingFormat.VFPURegisterTypes[regIndex]); regIndex++; break; case ASMElementTypeCharacter.PartialVFPURegister: partialRegValue[regIndex] = EncodePartialVFPURegister(args[argsIndex], encodingFormat.VFPURegisterTypes[regIndex], encodingFormat.PartialRegisterSizes, encodingFormat.PartialRegisterIncludeMasks[regIndex]); regIndex++; break; case ASMElementTypeCharacter.InvertedSingleBitVFPURegister: regValue[regIndex] = EncodeInvertedSingleBitVFPURegister(args[argsIndex], encodingFormat.VFPURegisterTypes[regIndex]); regIndex++; break; case ASMElementTypeCharacter.Cop0Register: regValue[regIndex] = EncodeCop0Register(args[argsIndex]); regIndex++; break; case ASMElementTypeCharacter.GTEControlRegister: regValue[regIndex] = EncodeGTEControlRegister(args[argsIndex]); regIndex++; break; case ASMElementTypeCharacter.GTEDataRegister: regValue[regIndex] = EncodeGTEDataRegister(args[argsIndex]); regIndex++; break; case ASMElementTypeCharacter.SignedImmediate: case ASMElementTypeCharacter.UnsignedImmediate: immedValue[immedIndex] = EncodeImmediate(args[argsIndex], encodingFormat.ImmediateLengths[immedIndex], (uint)encodingFormat.ImmediateIncludeMasks[immedIndex]); immedIndex++; break; case ASMElementTypeCharacter.BranchImmediate: immedValue[immedIndex] = EncodeBranchImmediate(args[argsIndex], pc, (uint)encodingFormat.ImmediateIncludeMasks[immedIndex]); immedIndex++; break; case ASMElementTypeCharacter.JumpImmediate: immedValue[immedIndex] = EncodeJumpImmediate(args[argsIndex], 26, pc); immedIndex++; break; case ASMElementTypeCharacter.DecrementedImmediate: immedValue[immedIndex] = EncodeDecrementedImmediate(args[argsIndex], encodingFormat.ImmediateLengths[immedIndex], (uint)encodingFormat.ImmediateIncludeMasks[immedIndex]); immedIndex++; break; case ASMElementTypeCharacter.ModifiedImmediate: immedValue[immedIndex] = EncodeModifiedImmediate(args[argsIndex], args[argsIndex - 1], encodingFormat.ImmediateLengths[immedIndex], (uint)encodingFormat.ImmediateIncludeMasks[immedIndex]); immedIndex++; break; case ASMElementTypeCharacter.ShiftedImmediate: immedValue[immedIndex] = EncodeShiftedImmediate(args[argsIndex], encodingFormat.ImmediateLengths[immedIndex], encodingFormat.ShiftedImmediateAmounts[immedIndex], (uint)encodingFormat.ImmediateIncludeMasks[immedIndex]); immedIndex++; break; case ASMElementTypeCharacter.VFPUPrefixImmediate: immedValue[immedIndex] = EncodeVFPUPrefixImmediate(args[argsIndex], encodingFormat.VFPUPrefixType, encodingFormat.ImmediateLengths[immedIndex]); immedIndex++; break; default: incrementArgsIndex = false; break; } if (incrementArgsIndex) { argsIndex++; } } /* * // Replace bracket blocks in format with appropriate values * for (int i = 0; i < regIndex; i++) * { * newFormat = newFormat.Replace("[" + encodingFormat.RegisterTypes[i] + (i + 1) + "]", regBinary[i]); * * if (partialRegBinary[i] != null) * { * newFormat = newFormat.Replace("[" + encodingFormat.RegisterTypes[i] + (i + 1) + "-1]", partialRegBinary[i][0]); * newFormat = newFormat.Replace("[" + encodingFormat.RegisterTypes[i] + (i + 1) + "-2]", partialRegBinary[i][1]); * } * } * for (int i = 0; i < immedIndex; i++) * { * newFormat = newFormat.Replace("[" + encodingFormat.ImmediateTypes[i] + (i + 1) + "]", immedBinary[i]); * } * * binary = newFormat; */ uint uEncodingValue = encodingFormat.BaseEncoding; for (int i = 0; i < regIndex; i++) { if (regValue[i] != null) { uEncodingValue |= (((uint)regValue[i]) << encodingFormat.RegisterPositions[i]); } else if (partialRegValue[i] != null) { uEncodingValue |= (((uint)partialRegValue[i][0]) << encodingFormat.PartialRegisterPositions[i][0]); uEncodingValue |= (((uint)partialRegValue[i][1]) << encodingFormat.PartialRegisterPositions[i][1]); } } for (int i = 0; i < immedIndex; i++) { uEncodingValue |= (immedValue[i] << encodingFormat.ImmediatePositions[i]); } //byte[] bytes = BitConverter.GetBytes(uEncodingValue); byte[] bytes = ASMValueHelper.ConvertUIntToBytes(uEncodingValue, littleEndian); if (littleEndian) { uEncodingValue = ASMValueHelper.ReverseBytes(uEncodingValue); } //else //{ // Array.Reverse(bytes); //} string hex = ASMValueHelper.UnsignedToHex_WithLength(uEncodingValue, 8).ToUpper(); return(new ASMSingleEncodeResult(hex, bytes)); }
public byte[] UpdateBlockReferences(byte[] bytes, uint pc, bool littleEndian, IEnumerable <BlockMove> blockMoves) { int byteCount = bytes.Length; if (byteCount < 4) { return(bytes); } byte[] resultBytes = new byte[byteCount]; int startIndex = 0; byte[] asmBytes = bytes; if (byteCount > 4) { uint offsetBytes = pc % 4; if (offsetBytes != 0) { uint skipBytes = 4 - offsetBytes; pc = pc + skipBytes; startIndex += (int)skipBytes; int length = (int)(bytes.Length - skipBytes); byte[] newBytes = new byte[length]; Array.Copy(bytes, skipBytes, newBytes, 0, length); Array.Copy(bytes, 0, resultBytes, 0, startIndex); asmBytes = newBytes; } } uint[] instructions = ASMValueHelper.GetUintArrayFromBytes(asmBytes, littleEndian); int numInstructions = instructions.Length; uint[] newInstructions = new uint[numInstructions]; uint[] regLuiValues = new uint[32]; int[] regLuiIndexes = new int[32]; for (int regNum = 0; regNum < 32; regNum++) { regLuiIndexes[regNum] = -1; } for (int index = 0; index < numInstructions; index++) { uint uBinaryLine = instructions[index]; uint opcode = (uBinaryLine >> 26); uint newInstruction = uBinaryLine; // Is unconditional jump literal command J or JAL if ((opcode & 0x3E) == 0x02) // ((opcode & 0b111110) == 0b000010) { uint jumpAddress = (((uBinaryLine & 0x03FFFFFFU) << 2) | (pc & 0xF0000000U)); foreach (BlockMove blockMove in blockMoves) { if ((jumpAddress >= blockMove.Location) && (jumpAddress < blockMove.EndLocation)) { uint newJumpAddress = (uint)(jumpAddress + blockMove.Offset); newInstruction = (opcode << 26) | ((newJumpAddress >> 2) & 0x03FFFFFFU); } } } // Is Load Upper Immediate (LUI) EncodingFormat encFormat = Decoder.FormatHelper.FindFormatByBinary(uBinaryLine); if (encFormat.Command == "lui") { int regNum = (int)(uBinaryLine >> encFormat.RegisterPositions[0] & encFormat.RegisterIncludeMasks[0]); uint immediate = (uint)(uBinaryLine >> encFormat.ImmediatePositions[0] & encFormat.ImmediateIncludeMasks[0]); regLuiValues[regNum] = immediate; regLuiIndexes[regNum] = index; } // Is Load or Store command, or ADDI, ADDIU, or ORI if (IsLoadCommand(encFormat.Command) || IsStoreCommand(encFormat.Command) || ((encFormat.Command == "addi") || (encFormat.Command == "addiu") || (encFormat.Command == "ori"))) { int regNum = (int)(uBinaryLine >> encFormat.RegisterPositions[1] & encFormat.RegisterIncludeMasks[1]); if (regLuiIndexes[regNum] >= 0) { short offset = ASMValueHelper.UnsignedShortToSignedShort((ushort)(uBinaryLine & 0xffff)); uint targetAddress = (uint)((regLuiValues[regNum] << 16) + offset) | (0x80000000U); foreach (BlockMove blockMove in blockMoves) { if ((targetAddress >= blockMove.Location) && (targetAddress < blockMove.EndLocation)) { uint newTargetAddress = (uint)(targetAddress + blockMove.Offset); uint newLuiValue = (ushort)(newTargetAddress >> 16); ushort newOffset = (ushort)(newTargetAddress & 0xffff); if (encFormat.Command != "ori") { newLuiValue += (uint)((newOffset >= 0x8000) ? 1 : 0); } newInstruction = ((uBinaryLine & 0xFFFF0000U) | newOffset); // Modify the LUI if necessary if (newLuiValue != regLuiValues[regNum]) { uint newLuiInstruction = (newInstructions[regLuiIndexes[regNum]] & 0xFFFF0000U) | newLuiValue; newInstructions[regLuiIndexes[regNum]] = newLuiInstruction; byte[] newLuiInstructionBytes = ASMValueHelper.ConvertUIntToBytes(newLuiInstruction, littleEndian); Array.Copy(newLuiInstructionBytes, 0, resultBytes, (regLuiIndexes[regNum] * 4) + startIndex, 4); } } } } } newInstructions[index] = newInstruction; byte[] newBytes = ASMValueHelper.ConvertUIntToBytes(newInstruction, littleEndian); Array.Copy(newBytes, 0, resultBytes, (index * 4) + startIndex, 4); } for (int index = (numInstructions * 4) + startIndex; index < byteCount; index++) { resultBytes[index] = bytes[index]; } return(resultBytes); }