/// <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; }
/// <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); } }
/// <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); }