示例#1
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="ctx"></param>
 /// <param name="emitter"></param>
 protected override void Emit(Context ctx, MachineCodeEmitter emitter)
 {
     OpCode opCode = ComputeOpCode(ctx.Result, ctx.Operand1, ctx.Operand2);
     if (ctx.Operand1 is ConstantOperand)
     {
         ConstantOperand op = ctx.Operand1 as ConstantOperand;
         op = new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(CilElementType.U1), op.Value);
         emitter.Emit(opCode, ctx.Result, op);
     }
     else
         emitter.Emit(opCode, ctx.Operand1, null);
 }
        /// <summary>
        /// Splits the long operand into its high and low parts.
        /// </summary>
        /// <param name="operand">The operand to split.</param>
        /// <param name="operandLow">The low operand.</param>
        /// <param name="operandHigh">The high operand.</param>
        /// <exception cref="T:System.ArgumentException"><paramref name="operand"/> is not a ConstantOperand and not a MemoryOperand.</exception>
        public static void SplitLongOperand(Operand operand, out Operand operandLow, out Operand operandHigh)
        {
            if (operand.Type.Type != CilElementType.I8 && operand.Type.Type != CilElementType.U8)
            {
                operandLow = operand;
                operandHigh = new ConstantOperand(new SigType(CilElementType.I4), (int)0);
                return;
            }

            Debug.Assert(operand is MemoryOperand || operand is ConstantOperand, @"Long operand not memory or constant.");

            if (operand is ConstantOperand)
                SplitFromConstantOperand(operand, out operandLow, out operandHigh);
            else
                SplitFromNonConstantOperand(operand, out operandLow, out operandHigh);
        }
 /// <summary>
 /// Visitation function for <see cref="CIL.ICILVisitor.Ldsflda"/>.
 /// </summary>
 /// <param name="ctx">The context.</param>
 void CIL.ICILVisitor.Ldsflda(Context ctx)
 {
     Runtime.Linker.LinkerSymbol symbol = MethodCompiler.Linker.GetSymbol(ctx.RuntimeField);
     //Operand eax = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EAX);
     Operand address = new ConstantOperand(new SigType(CilElementType.I4), (int)MethodCompiler.Linker.BaseAddress + symbol.SectionAddress);
     ctx.SetInstruction(CPUx86.Instruction.MovInstruction, ctx.Result, address);
 }
        /// <summary>
        /// Creates the IVT method.
        /// </summary>
        /// <param name="compiler">The compiler.</param>
        private void CreateIVTMethod(AssemblyCompiler compiler)
        {
            InstructionSet set = new InstructionSet(4048);
            Context ctx = new Context(set, -1);

            ctx.SetInstruction(IR.Instruction.PrologueInstruction);
            ctx.Other = 0; // stacksize

            // Create the IVT Table
            SigType I4 = new SigType(CilElementType.I4);
            RegisterOperand ecx = new RegisterOperand(I4, GeneralPurposeRegister.ECX);
            RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX);
            RegisterOperand ebx = new RegisterOperand(I4, GeneralPurposeRegister.EBX);

            ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, ecx, new ConstantOperand(I4, (int)0x201000));

            for (int i = 0; i <= 256; i++)
            {
                LinkerSymbol symbol = _linker.GetSymbol(@"Mosa.Tools.Compiler.LinkerGenerated.<$>InterruptISR" + i.ToString() + "()");
                Operand address = new ConstantOperand(I4, (int)_linker.GetSection(SectionKind.Text).VirtualAddress + symbol.SectionAddress);
                ctx.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(I4, ecx.Register, new IntPtr(i * 4)), address);
            }

            ctx.AppendInstruction(IR.Instruction.EpilogueInstruction);
            ctx.Other = 0;

            CompilerGeneratedMethod method = LinkTimeCodeGenerator.Compile(compiler, @"InterruptInit", set);
        }
        /// <summary>
        /// Visitation function for <see cref="ICILVisitor.Ldfld"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        public void Ldfld(Context ctx)
        {
            Operand resultOperand = ctx.Result;
            Operand objectOperand = ctx.Operand1;

            RuntimeField field = ctx.RuntimeField;
            IntPtr address = field.Address;
            ConstantOperand offsetOperand = new ConstantOperand(BuiltInSigType.IntPtr, address.ToInt64());

            IInstruction loadInstruction = Instruction.LoadInstruction;
            if (MustSignExtendOnLoad(field.SignatureType.Type))
            {
                loadInstruction = Instruction.SignExtendedMoveInstruction;
            }
            else if (MustZeroExtendOnLoad(field.SignatureType.Type))
            {
                loadInstruction = Instruction.ZeroExtendedMoveInstruction;
            }

            ctx.SetInstruction(loadInstruction, resultOperand, objectOperand, offsetOperand);
        }
 private Operand LoadArrayBaseAddress(Context ctx, SZArraySigType arraySignatureType, Operand arrayOperand)
 {
     Operand arrayAddress = this.MethodCompiler.CreateTemporary(new PtrSigType(arraySignatureType.ElementType));
     Operand fixedOffset = new ConstantOperand(BuiltInSigType.Int32, 12);
     ctx.SetInstruction(Instruction.AddSInstruction, arrayAddress, arrayOperand, fixedOffset);
     return arrayAddress;
 }
示例#7
0
        /// <summary>
        /// Compares with the given operand for equality.
        /// </summary>
        /// <param name="other">The other operand to compare with.</param>
        /// <returns>The return value is true if the operands are equal; false if not.</returns>
        public override bool Equals(Operand other)
        {
            ConstantOperand cop = other as ConstantOperand;

            return(null != cop && null != cop.Value && null != Value && cop.Value.Equals(Value));
        }
        private static void SplitFromConstantOperand(Operand operand, out Operand operandLow, out Operand operandHigh)
        {
            SigType HighType = (operand.Type.Type == CilElementType.I8) ? new SigType(CilElementType.I4) : new SigType(CilElementType.U4);
            SigType U4 = new SigType(CilElementType.U4);

            ConstantOperand constantOperand = operand as ConstantOperand;

            if (HighType.Type == CilElementType.I4)
            {
                long value = (long)constantOperand.Value;
                operandLow = new ConstantOperand(U4, (uint)(value & 0xFFFFFFFF));
                operandHigh = new ConstantOperand(HighType, (int)(value >> 32));
            }
            else
            {
                ulong value = (ulong)constantOperand.Value;
                operandLow = new ConstantOperand(U4, (uint)(value & 0xFFFFFFFF));
                operandHigh = new ConstantOperand(HighType, (uint)(value >> 32));
            }
        }
 /// <summary>
 /// Determines if the given constant operand is a large constant.
 /// </summary>
 /// <remarks>
 /// Only constants, which have special types or do not fit into an immediate argument
 /// are large and are moved to memory.
 /// </remarks>
 /// <param name="co">The constant operand to check.</param>
 /// <returns>True if the constant is large and needs to be moved to a literal.</returns>
 private static bool IsLargeConstant(ConstantOperand co)
 {
     return (Array.IndexOf<CilElementType>(_largeCilTypes, co.Type.Type) != -1);
 }
 /// <summary>
 /// Visitation function for <see cref="ICILVisitor.Neg"/>.
 /// </summary>
 /// <param name="ctx">The context.</param>
 public void Neg(Context ctx)
 {
     if (IsUnsigned(ctx.Operand1))
     {
         ConstantOperand zero = new ConstantOperand(ctx.Operand1.Type, 0UL);
         ctx.SetInstruction(Instruction.SubUInstruction, ctx.Result, zero, ctx.Operand1);
     }
     else
     {
         ConstantOperand minusOne = new ConstantOperand(ctx.Operand1.Type, -1L);
         ctx.SetInstruction(Instruction.MulSInstruction, ctx.Result, minusOne, ctx.Operand1);
     }
 }
示例#11
0
        /// <summary>
        /// Decodes the specified instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="decoder">The instruction decoder, which holds the code stream.</param>
        public override void Decode(Context ctx, IInstructionDecoder decoder)
        {
            // Decode base classes first
            base.Decode(ctx, decoder);

            ConstantOperand constantValueOperand;

            // Opcode specific handling
            switch (opcode)
            {
                case OpCode.Ldc_i4:
                    {
                        int i = decoder.DecodeInt();
                        constantValueOperand = new ConstantOperand(new SigType(CilElementType.I4), i);
                    }
                    break;

                case OpCode.Ldc_i4_s:
                    {
                        sbyte sb = decoder.DecodeSByte();
                        constantValueOperand = new ConstantOperand(new SigType(CilElementType.I4), sb);
                    }
                    break;

                case OpCode.Ldc_i8:
                    {
                        long l = decoder.DecodeLong();
                        constantValueOperand = new ConstantOperand(new SigType(CilElementType.I8), l);
                    }
                    break;

                case OpCode.Ldc_r4:
                    {
                        float f = decoder.DecodeFloat();
                        constantValueOperand = new ConstantOperand(new SigType(CilElementType.R4), f);
                    }
                    break;

                case OpCode.Ldc_r8:
                    {
                        double d = decoder.DecodeDouble();
                        constantValueOperand = new ConstantOperand(new SigType(CilElementType.R8), d);
                    }
                    break;

                case OpCode.Ldnull:
                    constantValueOperand = ConstantOperand.GetNull();
                    break;

                case OpCode.Ldc_i4_0:
                    constantValueOperand = ConstantOperand.FromValue(0);
                    break;

                case OpCode.Ldc_i4_1:
                    constantValueOperand = ConstantOperand.FromValue(1);
                    break;

                case OpCode.Ldc_i4_2:
                    constantValueOperand = ConstantOperand.FromValue(2);
                    break;

                case OpCode.Ldc_i4_3:
                    constantValueOperand = ConstantOperand.FromValue(3);
                    break;

                case OpCode.Ldc_i4_4:
                    constantValueOperand = ConstantOperand.FromValue(4);
                    break;

                case OpCode.Ldc_i4_5:
                    constantValueOperand = ConstantOperand.FromValue(5);
                    break;

                case OpCode.Ldc_i4_6:
                    constantValueOperand = ConstantOperand.FromValue(6);
                    break;

                case OpCode.Ldc_i4_7:
                    constantValueOperand = ConstantOperand.FromValue(7);
                    break;

                case OpCode.Ldc_i4_8:
                    constantValueOperand = ConstantOperand.FromValue(8);
                    break;

                case OpCode.Ldc_i4_m1:
                    constantValueOperand = ConstantOperand.FromValue(-1);
                    break;

                default:
                    throw new System.NotImplementedException();
            }

            ctx.Operand1 = constantValueOperand;
            ctx.Result = decoder.Compiler.CreateTemporary(constantValueOperand.Type);
        }
        /// <summary>
        /// Visitation function for Ldflda instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Ldflda(Context context)
        {
            Operand fieldAddress = context.Result;
            Operand objectOperand = context.Operand1;

            int offset = typeLayout.GetFieldOffset(context.RuntimeField);

            Operand fixedOffset = new ConstantOperand(BuiltInSigType.Int32, offset);
            context.SetInstruction(Instruction.AddUInstruction, fieldAddress, objectOperand, fixedOffset);
        }
        /// <summary>
        /// Visitation function for Ldfld instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Ldfld(Context context)
        {
            Operand resultOperand = context.Result;
            Operand objectOperand = context.Operand1;

            RuntimeField field = context.RuntimeField;
            //IntPtr address = field.Address;
            int offset = typeLayout.GetFieldOffset(field);
            ConstantOperand offsetOperand = new ConstantOperand(BuiltInSigType.IntPtr, offset);

            IInstruction loadInstruction = Instruction.LoadInstruction;
            if (MustSignExtendOnLoad(field.SignatureType.Type))
            {
                loadInstruction = Instruction.SignExtendedMoveInstruction;
            }
            else if (MustZeroExtendOnLoad(field.SignatureType.Type))
            {
                loadInstruction = Instruction.ZeroExtendedMoveInstruction;
            }

            context.SetInstruction(loadInstruction, resultOperand, objectOperand, offsetOperand);
        }
        /// <summary>
        /// Visitation function for Stfld instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Stfld(Context context)
        {
            Operand objectOperand = context.Operand1;
            Operand valueOperand = context.Operand2;

            //IntPtr address = context.RuntimeField.Address;
            int offset = typeLayout.GetFieldOffset(context.RuntimeField);
            ConstantOperand offsetOperand = new ConstantOperand(BuiltInSigType.IntPtr, offset);

            context.SetInstruction(Instruction.StoreInstruction, objectOperand, offsetOperand, valueOperand);
        }
 /// <summary>
 /// Visitation function for Neg instruction.
 /// </summary>
 /// <param name="context">The context.</param>
 public void Neg(Context context)
 {
     if (IsUnsigned(context.Operand1))
     {
         ConstantOperand zero = new ConstantOperand(context.Operand1.Type, 0UL);
         context.SetInstruction(Instruction.SubUInstruction, context.Result, zero, context.Operand1);
     }
     else if (context.Operand1.Type.Type == CilElementType.R4)
     {
         ConstantOperand minusOne = new ConstantOperand(context.Operand1.Type, -1.0f);
         context.SetInstruction(Instruction.MulFInstruction, context.Result, minusOne, context.Operand1);
     }
     else if (context.Operand1.Type.Type == CilElementType.R8)
     {
         ConstantOperand minusOne = new ConstantOperand(context.Operand1.Type, -1.0);
         context.SetInstruction(Instruction.MulFInstruction, context.Result, minusOne, context.Operand1);
     }
     else
     {
         ConstantOperand minusOne = new ConstantOperand(context.Operand1.Type, -1L);
         context.SetInstruction(Instruction.MulSInstruction, context.Result, minusOne, context.Operand1);
     }
 }
 /// <summary>
 /// Determines whether the value is zero.
 /// </summary>
 /// <param name="cilElementType">Type of the cil element.</param>
 /// <param name="constantOperand">The constant operand.</param>
 /// <returns>
 /// 	<c>true</c> if the value is zero; otherwise, <c>false</c>.
 /// </returns>
 private static bool IsValueZero(Metadata.CilElementType cilElementType, ConstantOperand constantOperand)
 {
     switch (cilElementType)
     {
         case Metadata.CilElementType.Char: goto case Metadata.CilElementType.U2;
         case Metadata.CilElementType.U1: return (byte)(constantOperand.Value) == 0;
         case Metadata.CilElementType.U2: return (ushort)(constantOperand.Value) == 0;
         case Metadata.CilElementType.U4: return (int)(constantOperand.Value) == 0;
         case Metadata.CilElementType.I1: return (sbyte)(constantOperand.Value) == 0;
         case Metadata.CilElementType.I2: return (short)(constantOperand.Value) == 0;
         case Metadata.CilElementType.I4: return (int)(constantOperand.Value) == 0;
         case Metadata.CilElementType.R4: return (float)(constantOperand.Value) == 0;
         case Metadata.CilElementType.R8: return (double)(constantOperand.Value) == 0;
         case Metadata.CilElementType.I: goto case Metadata.CilElementType.I4;
         case Metadata.CilElementType.U: goto case Metadata.CilElementType.U4;
         default: goto case Metadata.CilElementType.I4;
     }
 }
        /// <summary>
        /// Visitation function for <see cref="ICILVisitor.Stfld"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        public void Stfld(Context ctx)
        {
            Operand objectOperand = ctx.Operand1;
            Operand valueOperand = ctx.Operand2;

            IntPtr address = ctx.RuntimeField.Address;
            ConstantOperand offsetOperand = new ConstantOperand(BuiltInSigType.IntPtr, address.ToInt64());

            ctx.SetInstruction(Instruction.StoreInstruction, objectOperand, offsetOperand, valueOperand);
        }
        /// <summary>
        /// Visitation function for <see cref="ICILVisitor.UnaryBranch"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        public void UnaryBranch(Context ctx)
        {
            IBranch branch = ctx.Branch;

            ConditionCode cc;
            Operand first = ctx.Operand1;
            Operand second = new ConstantOperand(BuiltInSigType.Int32, 0UL);

            OpCode opcode = ((ICILInstruction)ctx.Instruction).OpCode;
            if (opcode == OpCode.Brtrue || opcode == OpCode.Brtrue_s)
            {
                cc = ConditionCode.NotEqual;
            }
            else if (opcode == OpCode.Brfalse || opcode == OpCode.Brfalse_s)
            {
                cc = ConditionCode.Equal;
            }
            else
            {
                throw new NotSupportedException(@"CILTransformationStage.UnaryBranch doesn't support CIL opcode " + opcode);
            }

            Operand comparisonResult = this.MethodCompiler.CreateTemporary(BuiltInSigType.Int32);
            ctx.SetInstruction(Instruction.IntegerCompareInstruction, comparisonResult, first, second);
            ctx.ConditionCode = cc;

            ctx.AppendInstruction(Instruction.BranchInstruction, comparisonResult);
            ctx.ConditionCode = cc;
            ctx.SetBranch(branch.Targets[0]);
        }
        private Operand CalculateArrayElementOffset(Context ctx, SZArraySigType arraySignatureType, Operand arrayIndexOperand)
        {
            int elementSizeInBytes = 0, alignment = 0;
            this.Architecture.GetTypeRequirements(arraySignatureType.ElementType, out elementSizeInBytes, out alignment);

            //
            // The sequence we're emitting is:
            //
            //      offset = arrayIndexOperand * elementSize
            //      temp = offset + 12
            //      result = *(arrayOperand * temp)
            //
            // The array data starts at offset 12 from the array object itself. The 12 is a hardcoded assumption
            // of x86, which might change for other platforms. We need to refactor this into some helper classes.
            //

            Operand elementOffset = this.MethodCompiler.CreateTemporary(BuiltInSigType.Int32);
            Operand elementSizeOperand = new ConstantOperand(BuiltInSigType.Int32, elementSizeInBytes);
            ctx.AppendInstruction(IR.Instruction.MulSInstruction, elementOffset, arrayIndexOperand, elementSizeOperand);

            return elementOffset;
        }
        /// <summary>
        /// Expands the unary branch instruction for 64-bits.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandUnaryBranch(Context context)
        {
            Debug.Assert(context.Branch.Targets.Length == 2);

            int target = context.Branch.Targets[0];

            Operand op1H, op1L, op2H, op2L;
            Operand zero = new ConstantOperand(new SigType(CilElementType.I4), (int)0);
            SplitLongOperand(context.Operand1, out op1L, out op1H);
            SplitLongOperand(zero, out op2L, out op2H);
            IR.ConditionCode code;

            switch (((context.Instruction) as CIL.ICILInstruction).OpCode)
            {
                // Signed
                case CIL.OpCode.Brtrue: code = IR.ConditionCode.NotEqual; break;
                case CIL.OpCode.Brfalse: code = IR.ConditionCode.Equal; break;
                case CIL.OpCode.Beq_s: code = IR.ConditionCode.Equal; break;
                case CIL.OpCode.Bge_s: code = IR.ConditionCode.GreaterOrEqual; break;
                case CIL.OpCode.Bgt_s: code = IR.ConditionCode.GreaterThan; break;
                case CIL.OpCode.Ble_s: code = IR.ConditionCode.LessOrEqual; break;
                case CIL.OpCode.Blt_s: code = IR.ConditionCode.LessThan; break;

                // Unsigned
                case CIL.OpCode.Bne_un_s: code = IR.ConditionCode.NotEqual; break;
                case CIL.OpCode.Bge_un_s: code = IR.ConditionCode.UnsignedGreaterOrEqual; break;
                case CIL.OpCode.Bgt_un_s: code = IR.ConditionCode.UnsignedGreaterThan; break;
                case CIL.OpCode.Ble_un_s: code = IR.ConditionCode.UnsignedLessOrEqual; break;
                case CIL.OpCode.Blt_un_s: code = IR.ConditionCode.UnsignedLessThan; break;

                // Long form signed
                case CIL.OpCode.Beq: goto case CIL.OpCode.Beq_s;
                case CIL.OpCode.Bge: goto case CIL.OpCode.Bge_s;
                case CIL.OpCode.Bgt: goto case CIL.OpCode.Bgt_s;
                case CIL.OpCode.Ble: goto case CIL.OpCode.Ble_s;
                case CIL.OpCode.Blt: goto case CIL.OpCode.Blt_s;

                // Long form unsigned
                case CIL.OpCode.Bne_un: goto case CIL.OpCode.Bne_un_s;
                case CIL.OpCode.Bge_un: goto case CIL.OpCode.Bge_un_s;
                case CIL.OpCode.Bgt_un: goto case CIL.OpCode.Bgt_un_s;
                case CIL.OpCode.Ble_un: goto case CIL.OpCode.Ble_un_s;
                case CIL.OpCode.Blt_un: goto case CIL.OpCode.Blt_un_s;
                default: throw new NotImplementedException();
            }

            //UNUSED:
            //IR.ConditionCode conditionHigh = GetHighCondition(code);

            Context[] newBlocks = CreateEmptyBlockContexts(context.Label, 3);
            Context nextBlock = SplitContext(context, false);

            context.SetInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[0].BasicBlock);
            LinkBlocks(context, newBlocks[0]);
            // Compare high dwords
            newBlocks[0].AppendInstruction(CPUx86.Instruction.DirectCompareInstruction, op1H, op2H);
            // Branch if check already gave results
            newBlocks[0].AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal, newBlocks[2].BasicBlock);
            newBlocks[0].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[1].BasicBlock);
            LinkBlocks(newBlocks[0], newBlocks[1], newBlocks[2]);

            newBlocks[1].AppendInstruction(CPUx86.Instruction.BranchInstruction, code, FindBlock(target));
            //            newBlocks[1].SetBranch(target);
            newBlocks[1].AppendInstruction(CPUx86.Instruction.JmpInstruction);
            newBlocks[1].SetBranch(nextBlock.BasicBlock);
            LinkBlocks(newBlocks[1], FindBlock(target));
            LinkBlocks(newBlocks[1], nextBlock);

            // Compare low dwords
            newBlocks[2].SetInstruction(CPUx86.Instruction.DirectCompareInstruction, op1L, op2L);
            // Set the unsigned result...
            newBlocks[2].AppendInstruction(CPUx86.Instruction.BranchInstruction, code, FindBlock(target));
            //            newBlocks[1].SetBranch(target);
            newBlocks[2].AppendInstruction(CPUx86.Instruction.JmpInstruction);
            newBlocks[2].SetBranch(nextBlock.BasicBlock);
            LinkBlocks(newBlocks[2], FindBlock(target));
            LinkBlocks(newBlocks[2], nextBlock);
        }
        /// <summary>
        /// Visitation function for Ldflda instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Ldflda(Context context)
        {
            Operand fieldAddress = context.Result;
            Operand objectOperand = context.Operand1;

            Operand fixedOffset = new ConstantOperand(BuiltInSigType.Int32, context.RuntimeField.Address.ToInt32());
            context.SetInstruction(Instruction.AddUInstruction, fieldAddress, objectOperand, fixedOffset);
        }