コード例 #1
0
ファイル: Stfld.cs プロジェクト: sramos30/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if the value to store is floating point or
        /// if the value is not 4 or 8 bytes in size.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            int       metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            FieldInfo theField      = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);

            Types.TypeInfo  objTypeInfo   = conversionState.TheILLibrary.GetTypeInfo(theField.DeclaringType);
            Types.TypeInfo  fieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
            Types.FieldInfo theFieldInfo  = conversionState.TheILLibrary.GetFieldInfo(objTypeInfo, theField.Name);


            int offset = theFieldInfo.OffsetInBytes;

            int stackSize = fieldTypeInfo.SizeOnStackInBytes;
            int memSize   = fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : stackSize;

            StackItem value      = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem objPointer = conversionState.CurrentStackFrame.Stack.Pop();

            if (value.isFloat)
            {
                //SUPPORT - floats
                throw new NotSupportedException("Storing fields of type float not supported yet!");
            }

            //Get object pointer
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = stackSize.ToString() + "($sp)", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //Pop and mov value
            for (int i = 0; i < memSize; i += 2)
            {
                if (memSize - i == 1)
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Halfword, Dest = "$t0"
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "$t0", Dest = (offset + i).ToString() + "($t2)" });
                    GlobalMethods.StoreData(conversionState, theOp, "$t2", "$t0", (offset + i), 1);
                }
                else
                {
                    conversionState.Append(new ASMOps.Pop()
                    {
                        Size = ASMOps.OperandSize.Halfword, Dest = "$t0"
                    });
                    //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = (offset + i).ToString() + "($t2)" });
                    GlobalMethods.StoreData(conversionState, theOp, "$t2", "$t0", (offset + i), 2);
                }
            }
            //                                                           Rounds down             || Pop object pointer
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$sp", Src2 = ((((stackSize - memSize) / 2) * 2) + 4).ToString(), Dest = "$sp"
            });
        }
コード例 #2
0
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            MethodBase constructorMethod = theOp.MethodToCall;
            Type       objectType        = constructorMethod.DeclaringType;

            //New obj must:
            // - Ignore for creation of Delegates
            // - Allocate memory on the heap for the object
            //          - If no memory is left, throw a panic attack because we're out of memory...
            // - Call the specified constructor

            if (typeof(Delegate).IsAssignableFrom(objectType))
            {
                conversionState.Append(new ASMOps.Comment("Ignore newobj calls for Delegates"));
                //Still need to:
                // - Remove the "object" param but preserve the "function pointer"
                StackItem funcPtrItem = conversionState.CurrentStackFrame.Stack.Pop();;
                conversionState.CurrentStackFrame.Stack.Pop();
                conversionState.CurrentStackFrame.Stack.Push(funcPtrItem);

                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
                });
                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "4($sp)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory
                });
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$sp", Src2 = "4", Dest = "$sp"
                });
                return;
            }

            Types.MethodInfo constructorMethodInfo = conversionState.TheILLibrary.GetMethodInfo(constructorMethod);

            conversionState.AddExternalLabel(conversionState.GetNewObjMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(constructorMethodInfo.ID);

            int currOpPosition = conversionState.PositionOf(theOp);

            //Attempt to allocate memory on the heap for the new object
            //This involves:
            // - Pushing the type reference onto the stack
            // - Calling GC NewObj method
            // - Check the pointer == 0, if so, out of memory

            //Push type reference
            string typeIdStr = conversionState.TheILLibrary.GetTypeInfo(objectType).ID;

            conversionState.AddExternalLabel(typeIdStr);
            conversionState.Append(new ASMOps.La()
            {
                Dest = "$t4", Label = typeIdStr
            });
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Word, Src = "$t4"
            });
            //Push a word for return value (i.e. new object pointer)
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Word, Src = "$zero"
            });
            //Get the GC.NewObj method ID (i.e. ASM label)
            string methodLabel = conversionState.GetNewObjMethodInfo().ID;

            //Call GC.NewObj
            conversionState.Append(new ASMOps.Call()
            {
                Target = methodLabel
            });
            //Pop the return value (i.e. new object pointer)
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t0"
            });
            //Remove arg 0 from stack
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$sp", Src2 = "4", Dest = "$sp"
            });
            //Check if pointer == 0?
            //If it isn't 0, not out of memory so continue execution
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t0", DestILPosition = currOpPosition, Extension = "NotNullMem"
            });
            //If we are out of memory, we have a massive problem
            //Because it means we don't have space to create a new exception object
            //So ultimately we just have to throw a kernel panic
            //Throw a panic attack... ( :/ ) by calling kernel Halt(uint lastAddress)

            //result.AppendLine("call GetEIP");
            //result.AppendLine("push dword esp");
            //result.AppendLine("push dword ebp");
            //result.AppendLine("pushad");
            //result.AppendLine("mov dword eax, 0xDEADBEEF");
            //result.AppendLine("mov dword ebx, 0x1");
            //result.AppendLine("mov dword ecx, 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_GC_Enabled], 1");
            //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_Heap_PreventAllocation], 0");
            //result.AppendLine("jmp method_System_Void_RETEND_Kernel_PreReqs_DECLEND_PageFaultDetection_NAMEEND___Fail");

            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            //Insert the not null label
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "NotNullMem"
            });

            //Call the specified constructor
            //This involves:
            // - Push empty dword onto stack
            // - Move all args down by one dword
            // - Move object reference into dword as first arg
            // - Call constructor
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Word, Src = "$zero"
            });
            int sizeOfArgs = 0;

            ParameterInfo[] allParams = constructorMethod.GetParameters();
            foreach (ParameterInfo aParam in allParams)
            {
                sizeOfArgs += conversionState.TheILLibrary.GetTypeInfo(aParam.ParameterType).SizeOnStackInBytes;
                conversionState.CurrentStackFrame.Stack.Pop();
            }
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "$sp", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.RegToReg
            });
            if (sizeOfArgs > 0)
            {
                if (sizeOfArgs % 4 != 0)
                {
                    throw new InvalidOperationException("sizeOfArgs not exact multiple of 4!");
                }

                conversionState.Append(new ASMOps.Mov()
                {
                    Size = ASMOps.OperandSize.Word, Src = (sizeOfArgs / 4).ToString(), Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg
                });
                conversionState.Append(new ASMOps.Label()
                {
                    ILPosition = currOpPosition, Extension = "ShiftArgsLoop"
                });
                //Decrement counter ($t2)
                conversionState.Append(new ASMOps.Sub()
                {
                    Src1 = "$t2", Src2 = "1", Dest = "$t2"
                });
                //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t1)", Dest = "$t3" });
                GlobalMethods.LoadData(conversionState, theOp, "$t1", "$t3", 4, 4);
                //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t3", Dest = "0($t1)" });
                GlobalMethods.StoreData(conversionState, theOp, "$t1", "$t3", 0, 4);
                conversionState.Append(new ASMOps.Add()
                {
                    Src1 = "$t1", Src2 = "4", Dest = "$t1"
                });
                conversionState.Append(new ASMOps.Branch()
                {
                    BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t2", DestILPosition = currOpPosition, Extension = "ShiftArgsLoop"
                });
            }
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "0($t1)" });
            GlobalMethods.StoreData(conversionState, theOp, "$t1", "$t0", 0, 4);
            conversionState.Append(new ASMOps.Call()
            {
                Target = constructorMethodInfo.ID
            });
            //Only remove args from stack - we want the object pointer to remain on the stack
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$sp", Src2 = sizeOfArgs.ToString(), Dest = "$sp"
            });

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat            = false,
                sizeOnStackInBytes = 4,
                isNewGCObject      = true,
                isGCManaged        = true
            });
        }
コード例 #3
0
ファイル: Stelem.cs プロジェクト: zrbruce/FlingOS
        /// <summary>
        /// See base class documentation.
        /// </summary>
        /// <param name="theOp">See base class documentation.</param>
        /// <param name="conversionState">See base class documentation.</param>
        /// <returns>See base class documentation.</returns>
        /// <exception cref="System.NotSupportedException">
        /// Thrown if constant is a floating point number.
        /// </exception>
        public override void Convert(ILConversionState conversionState, ILOp theOp)
        {
            Type elementType = null;
            //bool pushValue = true;
            int  sizeToPop = 4;
            bool isFloat   = false;

            int currOpPosition = conversionState.PositionOf(theOp);

            conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID);
            conversionState.AddExternalLabel(conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID);

            switch ((OpCodes)theOp.opCode.Value)
            {
            case OpCodes.Stelem:
            {
                //Load the metadata token used to get the type info
                int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                //Get the type info for the element type
                elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
            }
            break;

            case OpCodes.Stelem_R4:
            case OpCodes.Stelem_R8:
                //TODO - Add more StElem op variants support
                throw new NotSupportedException("Stelem op variant not supported yet!");

            case OpCodes.Stelem_I1:
                sizeToPop   = 1;
                elementType = typeof(sbyte);
                break;

            case OpCodes.Stelem_I2:
                sizeToPop   = 2;
                elementType = typeof(Int16);
                break;

            case OpCodes.Stelem_Ref:
                elementType = null;
                break;

            case OpCodes.Stelem_I4:
                elementType = typeof(Int32);
                break;

            case OpCodes.Stelem_I8:
                sizeToPop   = 8;
                elementType = typeof(Int64);
                break;
            }

            if (isFloat)
            {
                //TODO - Support floats
                throw new NotSupportedException("StElem for floats not supported yet!");
            }

            //Get element from array and push the value onto the stack
            //                   (or for LdElemA push the address of the value)

            //This involves:
            // 1. Check array reference is not null
            //          - If it is, throw NullReferenceException
            // 2. Check array element type is correct
            //          - If not, throw ArrayTypeMismatchException
            // 3. Check index to get is > -1 and < array length
            //          - If not, throw IndexOutOfRangeException
            // 4. Calculate address of element
            // 5. Pop the value from the stack into the element

            //Stack setup upon entering this op: (top-most downwards)
            // 0. Value to store (word or 2 words)
            // 1. Index of element to get as Int32 (word)
            // 2. Array object reference as address (word)

            Types.TypeInfo arrayTypeInfo = conversionState.GetArrayTypeInfo();

            // 1. Check array reference is not null
            //      1.1. Move array ref into $t0
            //      1.2. Compare $t0 (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            //      1.4. Otherwise, call Exceptions.ThrowNullReferenceException

            //      1.1. Move array ref into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = (sizeToPop == 8 ? 12 : 8).ToString() + "($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      1.2. Compare $t0 (array ref) to 0
            //      1.3. If not zero, jump to continue execution further down
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t0", DestILPosition = currOpPosition, Extension = "Continue1"
            });
            //      1.4. Otherwise, call Exceptions.Throw1NullReferenceException
            conversionState.Append(new ASMOps.Call()
            {
                Target = "GetEIP"
            });
            conversionState.AddExternalLabel("GetEIP");
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue1"
            });

            // 2. Check array element type is correct
            //      2.1. Move element type ref into $t0
            //      2.2. Move element type ref from array object into $t1
            //      2.3. Compare $t0 to $t1
            //      2.4. If the same, jump to continue execution further down
            //      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException

            //string ContinueExecutionLabel2 = ContinueExecutionLabelBase + "2";
            ////      2.1. Move element type ref into $t0
            //if (elementType != null)
            //{
            //    result.AppendLine(string.Format("mov $t0, {0}", conversionState.GetTypeIdString(conversionState.GetTypeID(elementType))));
            //}
            //else
            //{
            //    //Should be the same for all classes since they are (indirectly) derived from ObjectWithType
            //    int typeOffset = conversionState.GetFieldOffset(arrayDBType, "_Type");

            //    //      - Move value (which is a ref) into $t0
            //    GlobalMethods.CheckAddrFromRegister(conversionState, "$sp", 0);
            //    result.AppendLine("mov $t0, 0($sp)");
            //    //      - Move value type ref (from value (ref)) into $t0
            //    GlobalMethods.CheckAddrFromRegister(conversionState, "$t0", typeOffset);
            //    result.AppendLine(string.Format("mov $t0, {0}($t0)", typeOffset));
            //}
            ////      2.2. Move element type ref from array object into $t1
            ////              - Move array ref into $t1
            //GlobalMethods.CheckAddrFromRegister(conversionState, "$sp", sizeToPop == 8 ? 12 : 8);
            //result.AppendLine(string.Format("mov $t1, {0}($sp)", sizeToPop == 8 ? 12 : 8));
            ////              - Move elemType ref (offset($t1)) into $t1
            int elemTypeOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "elemType").OffsetInBytes;

            //GlobalMethods.CheckAddrFromRegister(conversionState, "$t1", elemTypeOffset);
            //result.AppendLine(string.Format("mov $t1, {0}($t1)", elemTypeOffset));
            ////      2.3. Compare $t0 to $t1
            //result.AppendLine("cmp $t0, $t1");
            ////      2.4. If the same, jump to continue execution further down
            //result.AppendLine("je " + ContinueExecutionLabel2);
            ////      2.5. Otherwise, call Exceptions.ThrowArrayTypeMismatchException
            //result.AppendLine(string.Format("call {0}", conversionState.GetMethodID(conversionState.ThrowArrayTypeMismatchExceptionMethod)));
            //result.AppendLine(ContinueExecutionLabel2 + ":");

            // 3. Check index to get is > -1 and < array length
            //      3.1. Move index into $t0
            //      3.2. Move array length into $t1
            //      3.2. Compare $t0 to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            //      3.5. Compare $t0 to $t1
            //      3.6. Jump if less than to continue execution further down
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException

            //      3.1. Move index into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = (sizeToPop == 8 ? 8 : 4).ToString() + "($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      3.2. Move array length into $t2
            //              - Calculate the offset of the field from the start of the array object
            int lengthOffset = conversionState.TheILLibrary.GetFieldInfo(arrayTypeInfo, "length").OffsetInBytes;

            //              - Move array ref into $t1
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = (sizeToPop == 8 ? 12 : 8).ToString() + "($sp)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //              - Move length value (offset($t1)) into $t1
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = lengthOffset.ToString() + "($t1)", Dest = "$t1" });
            GlobalMethods.LoadData(conversionState, theOp, "$t1", "$t1", lengthOffset, 4);
            //      3.2. Compare $t0 to 0
            //      3.3. Jump if greater than to next test condition (3.5)
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.BranchGreaterThanEqual, Src1 = "$t0", Src2 = "$zero", DestILPosition = currOpPosition, Extension = "Continue3_1"
            });
            //      3.4. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_1"
            });
            //      3.5. Compare $t0 to $t1
            //      3.6. Jump if less than to continue execution further down
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.BranchLessThan, Src1 = "$t0", Src2 = "$t1", DestILPosition = currOpPosition, Extension = "Continue3_2"
            });
            //      3.7. Otherwise, call Exceptions.ThrowIndexOutOfRangeException
            conversionState.Append(new ASMOps.Call()
            {
                Target = conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID
            });
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue3_2"
            });

            // 4. Calculate address of element
            //      4.0. Pop value into $t2:$t1
            //      4.1. Pop index into $t3
            //      4.2. Pop array ref into $t0
            //      4.3. Move element type ref (from array ref) into $t0
            //      4.4. Push $t0
            //      4.5. Move IsValueType (from element ref type) into $t0
            //      4.6. If IsValueType, continue to 4.6., else goto 4.9.
            //      4.7. Pop $t0
            //      4.8. Move Size (from element type ref) into $t0
            //      4.9. Skip over 4.9. and 4.10.
            //      4.10. Pop $t0
            //      4.11. Move StackSize (from element type ref) into $t0
            //      4.12. Mulitply $t0 by $t3 (index by element size)
            //      4.13. Move array ref into $t3
            //      4.14. Add enough to go past Kernel.FOS_System.Array fields
            //      4.15. Add $t0 and $t1 (array ref + fields + (index * element size))

            //      4.0. Pop value into $t2:$t1
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t2"
            });
            if (sizeToPop == 8)
            {
                conversionState.Append(new ASMOps.Pop()
                {
                    Size = ASMOps.OperandSize.Word, Dest = "$t1"
                });
            }
            //      4.1. Pop index into $t3
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t3"
            });
            //      4.2. Move array ref into $t0
            conversionState.Append(new ASMOps.Mov()
            {
                Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg
            });
            //      4.3. Move element type ref (from array ref) into $t0
            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = elemTypeOffset.ToString() + "($t0)", Dest = "$t0" });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", elemTypeOffset, 4);
            //      4.4. Push $t0
            conversionState.Append(new ASMOps.Push()
            {
                Size = ASMOps.OperandSize.Word, Src = "$t0"
            });
            //      4.5. Move IsValueType (from element ref type) into $t0
            int isValueTypeOffset = conversionState.GetTypeFieldOffset("IsValueType");

            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = isValueTypeOffset.ToString() + "($t0)", Dest = "$t0" });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", isValueTypeOffset, 1);
            //      4.6. If IsValueType, continue to 4.7., else goto 4.9.
            conversionState.Append(new ASMOps.And()
            {
                Src1 = "$t0", Src2 = "1", Dest = "$t4"
            });
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.BranchZero, Src1 = "$t4", DestILPosition = currOpPosition, Extension = "Continue4_1"
            });
            //      4.7. Pop $t0
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t0"
            });
            //      4.8. Move Size (from element type ref) into $t0
            int sizeOffset = conversionState.GetTypeFieldOffset("Size");

            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = sizeOffset.ToString() + "($t0)", Dest = "$t0" });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", sizeOffset, 4);
            //      4.9. Skip over 4.9. and 4.10.
            conversionState.Append(new ASMOps.Branch()
            {
                BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "Continue4_2"
            });
            //      4.10. Pop $t0
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_1"
            });
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t0"
            });
            //      4.11. Move StackSize (from element type ref) into $t0
            int stackSizeOffset = conversionState.GetTypeFieldOffset("StackSize");

            //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = stackSizeOffset.ToString() + "($t0)", Dest = "$t0" });
            GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", stackSizeOffset, 4);
            //      4.12. Mulitply $t0 by $t3 (index by element size)
            conversionState.Append(new ASMOps.Label()
            {
                ILPosition = currOpPosition, Extension = "Continue4_2"
            });
            conversionState.Append(new ASMOps.Mul()
            {
                Src1 = "$t3", Src2 = "$t0"
            });
            conversionState.Append(new ASMOps.Mflo()
            {
                Dest = "$t0"
            });
            //      4.13. Pop array ref into $t3
            conversionState.Append(new ASMOps.Pop()
            {
                Size = ASMOps.OperandSize.Word, Dest = "$t3"
            });
            //      4.14. Add enough to go past Kernel.FOS_System.Array fields
            int allFieldsOffset = 0;

            #region Offset calculation
            {
                Types.FieldInfo highestOffsetFieldInfo = arrayTypeInfo.FieldInfos.Where(x => !x.IsStatic).OrderByDescending(x => x.OffsetInBytes).First();
                Types.TypeInfo  fieldTypeInfo          = conversionState.TheILLibrary.GetTypeInfo(highestOffsetFieldInfo.UnderlyingInfo.FieldType);
                allFieldsOffset = highestOffsetFieldInfo.OffsetInBytes + (fieldTypeInfo.IsValueType ? fieldTypeInfo.SizeOnHeapInBytes : fieldTypeInfo.SizeOnStackInBytes);
            }
            #endregion
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$t3", Src2 = allFieldsOffset.ToString(), Dest = "$t3"
            });
            //      4.15. Add $t0 and $t3 (array ref + fields + (index * element size))
            conversionState.Append(new ASMOps.Add()
            {
                Src1 = "$t3", Src2 = "$t0", Dest = "$t0"
            });

            // 5. Pop the element from the stack to array
            //      5.1. Move value in $t1:$t2 to 0($t0)
            if (sizeToPop == 8)
            {
                //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t2", Dest = "0($t0)" });
                GlobalMethods.StoreData(conversionState, theOp, "$t0", "$t2", 0, 4);
                //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t1", Dest = "4($t0)" });
                GlobalMethods.StoreData(conversionState, theOp, "$t0", "$t1", 4, 4);
            }
            else if (sizeToPop == 4)
            {
                //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t2", Dest = "0($t0)" });
                GlobalMethods.StoreData(conversionState, theOp, "$t0", "$t2", 0, 4);
            }
            else if (sizeToPop == 2)
            {
                //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Halfword, Src = "$t2", Dest = "0($t0)" });
                GlobalMethods.StoreData(conversionState, theOp, "$t0", "$t2", 0, 2);
            }
            else if (sizeToPop == 1)
            {
                //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "$t2", Dest = "0($t0)" });
                GlobalMethods.StoreData(conversionState, theOp, "$t0", "$t2", 0, 1);
            }

            //      5.2. Pop index, array ref and value from our stack
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
        }