示例#1
0
        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);
        }