/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { Operand result = context.Result; RegisterOperand tmp = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EDX); MemoryOperand operand = new MemoryOperand(context.Operand1.Type, GeneralPurposeRegister.EDX, new System.IntPtr(0)); context.SetInstruction(CPUx86.Instruction.MovInstruction, tmp, context.Operand1); context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, operand); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { Operand dest = context.Operand1; Operand value = context.Operand2; RegisterOperand edx = new RegisterOperand(dest.Type, GeneralPurposeRegister.EDX); RegisterOperand eax = new RegisterOperand(value.Type, GeneralPurposeRegister.EAX); MemoryOperand memory = new MemoryOperand(new SigType(context.InvokeTarget.Signature.Parameters[1].Type), GeneralPurposeRegister.EDX, new IntPtr(0)); context.SetInstruction(CPUx86.Instruction.MovInstruction, edx, dest); context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, value); context.AppendInstruction(CPUx86.Instruction.MovInstruction, memory, eax); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { MemoryOperand operand = new MemoryOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX, new System.IntPtr(0)); context.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX), context.Operand1); context.AppendInstruction(CPUx86.Instruction.LgdtInstruction, null, operand); RegisterOperand ax = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), GeneralPurposeRegister.EAX); RegisterOperand ds = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.DS); RegisterOperand es = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.ES); RegisterOperand fs = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.FS); RegisterOperand gs = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.GS); RegisterOperand ss = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.SS); context.AppendInstruction(CPUx86.Instruction.MovInstruction, ax, new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (int)0x00000010)); context.AppendInstruction(CPUx86.Instruction.MovInstruction, ds, ax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, es, ax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, fs, ax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, gs, ax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, ss, ax); context.AppendInstruction(CPUx86.Instruction.FarJmpInstruction); context.AppendInstruction(CPUx86.Instruction.NopInstruction); context.Previous.SetBranch(context.Offset); }
private static void SplitFromNonConstantOperand(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); // No, could be a member or a plain memory operand MemberOperand memberOperand = operand as MemberOperand; if (memberOperand != null) { // We need to keep the member reference, otherwise the linker can't fixup // the member address. operandLow = new MemberOperand(memberOperand.Member, U4, memberOperand.Offset); operandHigh = new MemberOperand(memberOperand.Member, HighType, new IntPtr(memberOperand.Offset.ToInt64() + 4)); } else { // Plain memory, we can handle it here MemoryOperand memoryOperand = (MemoryOperand)operand; operandLow = new MemoryOperand(U4, memoryOperand.Base, memoryOperand.Offset); operandHigh = new MemoryOperand(HighType, memoryOperand.Base, new IntPtr(memoryOperand.Offset.ToInt64() + 4)); } }
/// <summary> /// Emits the displacement operand. /// </summary> /// <param name="displacement">The displacement operand.</param> private void EmitDisplacement(MemoryOperand displacement) { byte[] disp; MemberOperand member = displacement as MemberOperand; LabelOperand label = displacement as LabelOperand; if (null != label) { int pos = (int)(_codeStream.Position - _codeStreamBasePosition); disp = LittleEndianBitConverter.GetBytes ((uint)_linker.Link (LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method, pos, 0, label.Name, IntPtr.Zero)); } else if (null != member) { int pos = (int)(_codeStream.Position - _codeStreamBasePosition); disp = LittleEndianBitConverter.GetBytes ((uint)_linker.Link (LinkType.AbsoluteAddress | LinkType.I4, _compiler.Method, pos, 0, member.Member, member.Offset)); } else { disp = LittleEndianBitConverter.GetBytes (displacement.Offset.ToInt32 ()); } _codeStream.Write (disp, 0, disp.Length); }
/// <summary> /// Calculates the value of the modR/M byte and SIB bytes. /// </summary> /// <param name="regField">The modR/M regfield value.</param> /// <param name="op1">The destination operand.</param> /// <param name="op2">The source operand.</param> /// <param name="sib">A potential SIB byte to emit.</param> /// <param name="displacement">An immediate displacement to emit.</param> /// <returns>The value of the modR/M byte.</returns> private static byte? CalculateModRM(byte? regField, Operand op1, Operand op2, out byte? sib, out MemoryOperand displacement) { byte? modRM = null; displacement = null; // FIXME: Handle the SIB byte sib = null; RegisterOperand rop1 = op1 as RegisterOperand, rop2 = op2 as RegisterOperand; MemoryOperand mop1 = op1 as MemoryOperand, mop2 = op2 as MemoryOperand; // Normalize the operand order if (null == rop1 && null != rop2) { // Swap the memory operands rop1 = rop2; rop2 = null; mop2 = mop1; mop1 = null; } if (null != regField) modRM = (byte)(regField.Value << 3); if (null != rop1 && null != rop2) { // mod = 11b, reg = rop1, r/m = rop2 modRM = (byte)((3 << 6) | (rop1.Register.RegisterCode << 3) | rop2.Register.RegisterCode); } // Check for register/memory combinations else if (null != mop2 && null != mop2.Base) { // mod = 10b, reg = rop1, r/m = mop2 modRM = (byte)(modRM.GetValueOrDefault () | (2 << 6) | (byte)mop2.Base.RegisterCode); if (null != rop1) { modRM |= (byte)(rop1.Register.RegisterCode << 3); } displacement = mop2; } else if (null != mop2) { // mod = 10b, r/m = mop1, reg = rop2 modRM = (byte)(modRM.GetValueOrDefault () | 5); if (null != rop1) { modRM |= (byte)(rop1.Register.RegisterCode << 3); } displacement = mop2; } else if (null != mop1 && null != mop1.Base) { // mod = 10b, r/m = mop1, reg = rop2 modRM = (byte)(modRM.GetValueOrDefault () | (2 << 6) | mop1.Base.RegisterCode); if (null != rop2) { modRM |= (byte)(rop2.Register.RegisterCode << 3); } displacement = mop1; } else if (null != mop1) { // mod = 10b, r/m = mop1, reg = rop2 modRM = (byte)(modRM.GetValueOrDefault () | 5); if (null != rop2) { modRM |= (byte)(rop2.Register.RegisterCode << 3); } displacement = mop1; } else if (null != rop1) { modRM = (byte)(modRM.GetValueOrDefault () | (3 << 6) | rop1.Register.RegisterCode); } return modRM; }
/// <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) { MemoryOperand mop = other as MemoryOperand; return(null != mop && mop.Type == Type && mop.Offset == Offset && mop.Base == Base); }
/// <summary> /// Visitation function for ThrowInstruction. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.ThrowInstruction(Context context) { int pointOfThrow = 4; int exceptionObject = 12; SigType u4 = new SigType(CilElementType.U4); RuntimeType runtimeType = typeSystem.GetType(@"Mosa.Platforms.x86.ExceptionEngine, Mosa.Platforms.x86"); RuntimeMethod runtimeMethod = runtimeType.FindMethod(@"ThrowException"); SymbolOperand method = SymbolOperand.FromMethod(runtimeMethod); //UNUSED: //Operand callTarget = context.Result; MemoryOperand pointOfThrowOperand = new MemoryOperand(u4, GeneralPurposeRegister.ESP, new IntPtr(pointOfThrow)); MemoryOperand exceptionObjectOperand = new MemoryOperand(u4, GeneralPurposeRegister.ESP, new IntPtr(exceptionObject)); RegisterOperand esp = new RegisterOperand(u4, GeneralPurposeRegister.ESP); RegisterOperand eax = new RegisterOperand(u4, GeneralPurposeRegister.EAX); // Save current stack context.SetInstruction(CPUx86.Instruction.PushInstruction, null, new RegisterOperand(u4, GeneralPurposeRegister.ESP)); // Save point of call context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, pointOfThrowOperand); // Pass thrown exception context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, exceptionObjectOperand); // Save registers context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new RegisterOperand(u4, GeneralPurposeRegister.EBP)); context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new RegisterOperand(u4, GeneralPurposeRegister.EDI)); context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new RegisterOperand(u4, GeneralPurposeRegister.ESI)); context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new RegisterOperand(u4, GeneralPurposeRegister.EBX)); context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new RegisterOperand(u4, GeneralPurposeRegister.EDX)); context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new RegisterOperand(u4, GeneralPurposeRegister.ECX)); context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, new RegisterOperand(u4, GeneralPurposeRegister.EAX)); // Pass them to the exception handling routine as parameters context.AppendInstruction(CPUx86.Instruction.SubInstruction, esp, new ConstantOperand(esp.Type, 40)); context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(u4, GeneralPurposeRegister.EDX), esp); for (int i = 0; i < 10; ++i) { context.AppendInstruction(CPUx86.Instruction.PopInstruction, eax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(u4, GeneralPurposeRegister.EDX, new IntPtr(i * 4)), eax); } // Call exception handling context.AppendInstruction(CPUx86.Instruction.CallInstruction, null, method); // Compile exception handling if necessary if (!exceptionHandlingCompiled) { //FIXME //this.methodCompiler.Scheduler.ScheduleTypeForCompilation(typeSystem.GetType(@"Mosa.Platforms.x86.RegisterContext, Mosa.Platforms.x86")); //this.methodCompiler.Scheduler.ScheduleTypeForCompilation(typeSystem.GetType(@"Mosa.Platforms.x86.ExceptionEngine, Mosa.Platforms.x86")); //(this.typeLayout as TypeLayoutStage).CreateSequentialLayout(typeSystem.GetType(@"Mosa.Platforms.x86.RegisterContext, Mosa.Platforms.x86")); //(this.typeLayout as TypeLayoutStage).CreateSequentialLayout(typeSystem.GetType(@"Mosa.Platforms.x86.ExceptionEngine, Mosa.Platforms.x86")); //(this.typeLayout as TypeLayoutStage).BuildMethodTable(typeSystem.GetType(@"Mosa.Platforms.x86.RegisterContext, Mosa.Platforms.x86")); //(this.typeLayout as TypeLayoutStage).BuildMethodTable(typeSystem.GetType(@"Mosa.Platforms.x86.ExceptionEngine, Mosa.Platforms.x86")); exceptionHandlingCompiled = true; } }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { MemoryOperand operand = new MemoryOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX, new System.IntPtr(0)); context.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX), context.Operand1); context.AppendInstruction(CPUx86.Instruction.LidtInstruction, null, operand); }