Пример #1
0
 public Instruction(InstructionHelper helper, int byteCode, int index)
 {
     Helper             = helper;
     AssociatedByteCode = byteCode;
     Index = index;
     foreach (OpcodeParamaterUnmaskingMetas pMetas in helper.ParamaterUnmaskingMetas)
     {
         Params.Add(new FunctionalParam(this, pMetas.Parameter, pMetas.ShiftAmount, pMetas.BitMaskAfterShift));
     }
 }
Пример #2
0
        public static void Fit(Opcode opcode, List <BitField> bitFields, List <ParameterBitField> parameters)
        {
            // Because the way the algorithm works and recognises fields with a value of 0
            //   in the matrix array to cause it to return the Unidentifiable, a dummy
            //   InstructionHelper is created and then automatically added to the list
            // Point being: nothing important other than NOP should be put in the 0th element
            //   because 0 will never be recognised as an instruction in the matrix.
            bool thisIsTheNop = false;

            if (InstructionHelper.Helpers.Count == 0)
            {
                if (bitFields[0].GetType() == typeof(ZeroBitField))
                {
                    if (bitFields[0].Length == Opcode.InstructionSizeInBits)
                    {
                        //NOPIsIdentifiedByAllZeroes = true;
                        thisIsTheNop = true;
                    }
                }
                else
                {
                    InstructionHelper.Helpers.Add(null);
                    opcode.ListId += 1;
                }
            }
            InstructionHelper helper = new InstructionHelper(
                opcode.Name, opcode.ListId, bitFields, parameters
                );

            // The NOP should not be fitted if it is comprised of all 0s, because it will
            //   certainly cause a short in the matrix.
            // If the NOP is comprised of all 0s, the decoder and encoder will know how to
            //   handle it based on the NOPIsIdentifiedByAllZeroes switch.
            if (thisIsTheNop)
            {
                return;
            }
            int i             = 0;
            int bitsAddressed = 0;
            List <List <OpcodeIdentifierFitmentMetas> > opcodeIdentifierFitmentMetas = new List <List <OpcodeIdentifierFitmentMetas> >();

            for (; i <= BitField.maximumPrecedenceSetting; i++)
            {
                opcodeIdentifierFitmentMetas.Add(new List <OpcodeIdentifierFitmentMetas>());
            }

            // Sort the paramaters from the identifiers and various other work for data required later
            foreach (BitField bf in bitFields)
            {
                if (bf.GetType().BaseType == typeof(IdentifierBitField))
                {
                    IdentifierBitField idbf = (IdentifierBitField)bf;
                    int identifier          = idbf.Identifier;
                    if (!(bf.GetType() == typeof(ZeroBitField)))
                    {
                        helper.BitwiseIdentity += identifier << (Opcode.InstructionSizeInBits - (bitsAddressed + bf.Length));
                    }
                    opcodeIdentifierFitmentMetas[idbf.Precedence].Add(new OpcodeIdentifierFitmentMetas(identifier, bf.Length, bitsAddressed));
                }
                bitsAddressed += bf.Length;
            }
            if (bitsAddressed != Opcode.InstructionSizeInBits)
            {
                throw new Exception($"Instruction {opcode.Name} has {bitsAddressed} bits when Opcode.InstructionSizeInBits is {Opcode.InstructionSizeInBits}.");
            }

            // The parameter unmasking metas should appear in order of the appearance parameters
            foreach (ParameterBitField pbf in parameters)
            {
                bitsAddressed = 0;
                foreach (BitField bf in bitFields)
                {
                    if (bf.GetType() == pbf.GetType())
                    {
                        int shiftAmount       = Opcode.InstructionSizeInBits - (bf.Length + bitsAddressed);
                        int bitMaskAfterShift = (1 << bf.Length) - 1;
                        helper.ParamaterUnmaskingMetas.Add(new OpcodeParamaterUnmaskingMetas(bitMaskAfterShift, shiftAmount, (ParameterBitField)bf));
                        break;
                    }
                    bitsAddressed += bf.Length;
                }
            }

            // Take all ZeroBitFields over the length of 6 and split them up into more ZeroBitFields with a max length of 6 each
            // The reason for this is 0b111_111 = 63 = the max length of our defined matrix array layers
            // Also, or else the one code with a ZeroBitField(20) would require a layer 0b1111_1111_1111_1111_1111 = 1,048,575‬ elements long
            // The algorithm also requires consistency among the layers, each will be 66 elements long, element 65 and 66 reserved for bit
            //   masking data detailing how to traverse the particular layer.
            // It is a case of performance < RAM consumption, though this algorithm may be able to be tweaked, who knows.
            i = 0;
            // ZeroBitFields should always be at the max setting. They should be tested against after everything else.
            int max = BitField.maximumPrecedenceSetting;

            while (i < opcodeIdentifierFitmentMetas[max].Count)
            {
                int length = opcodeIdentifierFitmentMetas[max][i].Length;
                bitsAddressed = opcodeIdentifierFitmentMetas[max][i].BitsAddressed;
                if (length > 6)
                {
                    opcodeIdentifierFitmentMetas[max][i].Length = 6;
                    int amountOver = length - 6;
                    opcodeIdentifierFitmentMetas[max].Insert(i + 1, new OpcodeIdentifierFitmentMetas(0, amountOver, bitsAddressed + 6));
                }
                i++;
            }
            List <OpcodeIdentifierFitmentMetas> orderedIdentifierBitFieldMetas = new List <OpcodeIdentifierFitmentMetas>();

            foreach (List <OpcodeIdentifierFitmentMetas> bitFieldList in opcodeIdentifierFitmentMetas)
            {
                orderedIdentifierBitFieldMetas.AddRange(bitFieldList);
            }

            // Now the in the presence of the required data in the correct order, the matrix can be fitted
            i = 0;
            int offset = 0;

            foreach (OpcodeIdentifierFitmentMetas fitmentMeta in orderedIdentifierBitFieldMetas)
            {
                bool isFinalElement = ++i == orderedIdentifierBitFieldMetas.Count();
                int  shiftAmount    = Opcode.InstructionSizeInBits - (fitmentMeta.Length + fitmentMeta.BitsAddressed);
                int  bitMask        = (1 << fitmentMeta.Length) - 1;
                int  offsetNewIndex = offset + fitmentMeta.NewTargetMatrixIndex;
                if (MatrixArray[offset + MatrixLayerSize] == 0)
                {
                    MatrixArray[offset + MatrixLayerBitMaskSlot]     = bitMask;
                    MatrixArray[offset + MatrixLayerShiftAmountSlot] = shiftAmount;
                }
                if (isFinalElement)
                {
                    if (MatrixArray[offsetNewIndex] != 0) // This is bad
                    {
                        string errMsg = $"There's been a short while fitting the matrix.\n\n" +
                                        $"Instruction attempted to fit: {opcode.Name}\n";
                        if (MatrixArray[offsetNewIndex] < 0)
                        {
                            errMsg += $"Instruction that would've been written over: {InstructionHelper.Helpers[-MatrixArray[offsetNewIndex]].Name}\n";
                        }
                        else
                        {
                            errMsg += $"A part of the pathway to 1 more more instructions would've been overwritten.";
                        }
                        throw new Exception(errMsg);
                    }
                    MatrixArray[offsetNewIndex] = -opcode.ListId;
                    break;
                }
                if (MatrixArray[offsetNewIndex] == 0)
                {
                    Stack += MatrixLayerSize + 2; // +2 for the 2 bitMasking fields
                    MatrixArray[offsetNewIndex] = Stack;
                    offset = Stack;
                }
                else
                {
                    offset = MatrixArray[offsetNewIndex];
                }
            }
        }