/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { // Retrieve register context //context.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EAX), new MemoryOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.ESP, new IntPtr(28))); // Restore registers (Note: EAX and EDX are NOT restored!) //context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EDX), new MemoryOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EAX, new IntPtr(28))); //context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EBX), new MemoryOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EAX, new IntPtr(4))); //context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EDI), new MemoryOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EAX, new IntPtr(20))); //context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.ESI), new MemoryOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EAX, new IntPtr(16))); //context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.ESP), new MemoryOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EAX, new IntPtr(32))); //context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EBP), new MemoryOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EAX, new IntPtr(24))); //uint ebp, uint esp, int eip RegisterOperand edx = new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EDX); RegisterOperand ebp = new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.EBP); RegisterOperand esp = new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.ESP); // Restore registers context.AppendInstruction(X86.Mov, new RegisterOperand(BuiltInSigType.UInt32, GeneralPurposeRegister.ESP), context.Operand1); // Jmp to EIP (stored in EDX) context.AppendInstruction(X86.Jmp, null, edx); //context.SetOperand(0, edx); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { //var result = context.Result; var op2 = context.Operand1; var constant = Operand.CreateConstant(BuiltInSigType.IntPtr, parameters.Count * 4); var eax = Operand.CreateCPURegister(BuiltInSigType.IntPtr, GeneralPurposeRegister.EAX); // FIXME - need access to virtual register allocator var edx = Operand.CreateCPURegister(BuiltInSigType.IntPtr, GeneralPurposeRegister.EDX); // FIXME - need access to virtual register allocator var esp = Operand.CreateCPURegister(BuiltInSigType.IntPtr, GeneralPurposeRegister.ESP); // FIXME - need access to virtual register allocator var ebp = Operand.CreateCPURegister(BuiltInSigType.IntPtr, GeneralPurposeRegister.EBP); // FIXME - need access to virtual register allocator context.SetInstruction(X86.Sub, esp, constant); context.AppendInstruction(X86.Mov, edx, esp); var size = parameters.Count * 4; foreach (var parameter in parameters) { context.AppendInstruction(X86.Mov, Operand.CreateMemoryAddress(BuiltInSigType.IntPtr, edx, new IntPtr(size - 4)), Operand.CreateMemoryAddress(BuiltInSigType.IntPtr, ebp, new IntPtr(size + 8))); size -= 4; } context.AppendInstruction(X86.Mov, eax, op2); context.AppendInstruction(X86.Call, null, eax); context.AppendInstruction(X86.Add, esp, constant); //context.AppendInstruction(X86.Mov,result, Operand.CreateCPURegister(result.Type, GeneralPurposeRegister.EAX)); }
/// <summary> /// Adds the epilogue instructions. /// </summary> /// <param name="context">The context.</param> private void AddEpilogueInstructions(Context context) { Operand ebp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBP); Operand esp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); Operand edx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX); Operand edi = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDI); Operand ecx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ECX); Operand ebx = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX); context.SetInstruction(X86.Nop); if (SaveRegisters) { context.AppendInstruction(X86.Pop, ebx); context.AppendInstruction(X86.Pop, ecx); context.AppendInstruction(X86.Pop, edi); // Save EDX for int32 return values (or do not save EDX for non-int64 return values) if (!MethodCompiler.Method.Signature.ReturnType.IsUI8) { context.AppendInstruction(X86.Pop, edx); } } if (MethodCompiler.StackLayout.StackSize != 0) { context.AppendInstruction(X86.Add, esp, esp, Operand.CreateConstantSignedInt(TypeSystem, -MethodCompiler.StackLayout.StackSize)); } context.AppendInstruction(X86.Pop, ebp); context.AppendInstruction(X86.Ret); }
/// <summary> /// Visitation function for <see cref="IX86Visitor.Div"/> instructions. /// </summary> /// <param name="context">The context.</param> public void Div(Context context) { if (context.Result.IsCPURegister && context.Result2.IsCPURegister && context.Operand1.IsCPURegister) if (context.Result.Register == GeneralPurposeRegister.EDX && context.Result2.Register == GeneralPurposeRegister.EAX && context.Operand1.Register == GeneralPurposeRegister.EDX && context.Operand2.Register == GeneralPurposeRegister.EAX) return; Operand operand1 = context.Operand1; Operand operand2 = context.Operand2; Operand operand3 = context.Operand3; Operand result = context.Result; Operand result2 = context.Result2; Operand EAX = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); Operand EDX = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX); context.SetInstruction(X86.Mov, EDX, operand1); context.AppendInstruction(X86.Mov, EAX, operand2); if (operand3.IsCPURegister) { context.AppendInstruction2(X86.Div, EDX, EAX, EDX, EAX, operand3); } else { Operand v3 = AllocateVirtualRegister(TypeSystem.BuiltIn.I4); context.AppendInstruction(X86.Mov, v3, operand3); context.AppendInstruction2(X86.Div, EDX, EAX, EDX, EAX, v3); } context.AppendInstruction(X86.Mov, result2, EAX); context.AppendInstruction(X86.Mov, result, EDX); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { Operand result = context.Result; Operand eax = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4); context.AppendInstruction(X86.Add, eax, eax, Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.U4, GeneralPurposeRegister.ESP)); context.AppendInstruction(X86.Mov, eax, Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.U4, eax, 0)); context.AppendInstruction(X86.Mov, result, eax); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); context.SetInstruction(X86.Mov, esp, context.Operand1); context.AppendInstruction(X86.Popad); context.AppendInstruction(X86.Add, esp, esp, Operand.CreateConstant(methodCompiler.TypeSystem, 0x08)); context.AppendInstruction(X86.Sti); context.AppendInstruction(X86.IRetd); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { Operand esp = Operand.CreateCPURegister(BuiltInSigType.Int32, GeneralPurposeRegister.ESP); context.SetInstruction(X86.Mov, esp, context.Operand1); context.AppendInstruction(X86.Popad); context.AppendInstruction(X86.Add, esp, Operand.CreateConstant(BuiltInSigType.Int32, 0x08)); context.AppendInstruction(X86.Sti); context.AppendInstruction(X86.IRetd); }
/// <summary> /// Creates the interrupt service routine (ISR) methods. /// </summary> private void CreateInterruptVectors() { RuntimeType runtimeType = typeSystem.GetType(@"Mosa.Kernel.x86.IDT"); if (runtimeType == null) return; RuntimeMethod runtimeMethod = runtimeType.FindMethod(@"ProcessInterrupt"); if (runtimeMethod == null) return; Operand interruptMethod = Operand.CreateSymbolFromMethod(runtimeMethod); Operand esp = Operand.CreateCPURegister(BuiltInSigType.Int32, GeneralPurposeRegister.ESP); for (int i = 0; i <= 255; i++) { InstructionSet instructionSet = new InstructionSet(100); Context ctx = new Context(instructionSet); ctx.AppendInstruction(X86.Cli); if (i <= 7 || i >= 16 | i == 9) // For IRQ 8, 10, 11, 12, 13, 14 the cpu will automatically pushed the error code ctx.AppendInstruction(X86.Push, null, Operand.CreateConstant(BuiltInSigType.SByte, 0x0)); ctx.AppendInstruction(X86.Push, null, Operand.CreateConstant(BuiltInSigType.SByte, (byte)i)); ctx.AppendInstruction(X86.Pushad); ctx.AppendInstruction(X86.Call, null, interruptMethod); ctx.AppendInstruction(X86.Popad); ctx.AppendInstruction(X86.Add, esp, Operand.CreateConstant(BuiltInSigType.Int32, 0x08)); ctx.AppendInstruction(X86.Sti); ctx.AppendInstruction(X86.IRetd); LinkTimeCodeGenerator.Compile(this.compiler, @"InterruptISR" + i.ToString(), instructionSet, typeSystem); } }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { SigType I4 = BuiltInSigType.Int32; RegisterOperand esp = new RegisterOperand(I4, GeneralPurposeRegister.ESP); context.SetInstruction(X86.Mov, esp, context.Operand1); context.AppendInstruction(X86.Popad); context.AppendInstruction(X86.Add, esp, new ConstantOperand(I4, 0x08)); context.AppendInstruction(X86.Sti); context.AppendInstruction(X86.IRetd); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { Operand operand1 = context.Operand1; Operand operand2 = context.Operand2; RegisterOperand edx = new RegisterOperand(operand1.Type, GeneralPurposeRegister.EDX); RegisterOperand eax = new RegisterOperand(operand2.Type, GeneralPurposeRegister.EAX); context.SetInstruction(Instruction.MovInstruction, edx, operand1); context.AppendInstruction(Instruction.MovInstruction, eax, operand2); context.AppendInstruction(Instruction.OutInstruction, null, edx, eax); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { var dest = context.Operand1; var v0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM0); var zero = Operand.CreateConstant(methodCompiler.TypeSystem, 0); var offset16 = Operand.CreateConstant(methodCompiler.TypeSystem, 16); context.SetInstruction(X86.PXor, InstructionSize.Size128, v0, v0, v0); context.AppendInstruction(X86.MovupsStore, InstructionSize.Size128, dest, zero, v0); context.AppendInstruction(X86.MovupsStore, InstructionSize.Size128, dest, offset16, v0); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="methodCompiler">The method compiler.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { Operand result = context.Result; Operand methodAddress = context.Operand1; Operand newESP = context.Operand2; Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); context.SetInstruction(X86.Call, null, methodAddress); context.AppendInstruction(IRInstruction.Gen, eax); context.AppendInstruction(X86.Mov, result, eax); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { Operand operand1 = context.Operand1; Operand operand2 = context.Operand2; Operand edx = Operand.CreateCPURegister(operand1.Type, GeneralPurposeRegister.EDX); Operand eax = Operand.CreateCPURegister(operand2.Type, GeneralPurposeRegister.EAX); context.SetInstruction(X86.Mov, edx, operand1); context.AppendInstruction(X86.Mov, eax, operand2); context.AppendInstruction(X86.Out, null, edx, eax); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { Operand result = context.Result; SigType u4 = BuiltInSigType.UInt32; RegisterOperand eax = new RegisterOperand(u4, GeneralPurposeRegister.EAX); context.SetInstruction(X86.Pop, eax); context.AppendInstruction(X86.Add, eax, new RegisterOperand(u4, GeneralPurposeRegister.ESP)); context.AppendInstruction(X86.Mov, eax, new MemoryOperand(GeneralPurposeRegister.EAX, u4, new IntPtr(0))); context.AppendInstruction(X86.Mov, result, eax); context.AppendInstruction(X86.Push, null, eax); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { Operand result = context.Result; Operand operand = context.Operand1; Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); Operand ecx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ECX); Operand reg = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX); context.SetInstruction(X86.Mov, eax, operand); context.AppendInstruction(X86.Mov, ecx, methodCompiler.ConstantZero); context.AppendInstruction(X86.CpuId, eax, eax); context.AppendInstruction(X86.Mov, result, reg); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { Operand result = context.Result; Operand operand = context.Operand1; RegisterOperand eax = new RegisterOperand(BuiltInSigType.Int32, GeneralPurposeRegister.EAX); RegisterOperand ecx = new RegisterOperand(BuiltInSigType.Int32, GeneralPurposeRegister.ECX); RegisterOperand reg = new RegisterOperand(BuiltInSigType.Int32, GeneralPurposeRegister.EDX); context.SetInstruction(Instruction.MovInstruction, eax, operand); context.AppendInstruction(Instruction.XorInstruction, ecx, ecx); context.AppendInstruction(Instruction.CpuIdEdxInstruction); context.AppendInstruction(Instruction.MovInstruction, result, reg); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { Operand result = context.Result; Operand operand = context.Operand1; Operand eax = Operand.CreateCPURegister(BuiltInSigType.Int32, GeneralPurposeRegister.EAX); Operand ecx = Operand.CreateCPURegister(BuiltInSigType.Int32, GeneralPurposeRegister.ECX); Operand reg = Operand.CreateCPURegister(BuiltInSigType.Int32, GeneralPurposeRegister.EDX); context.SetInstruction(X86.Mov, eax, operand); context.AppendInstruction(X86.Xor, ecx, ecx); context.AppendInstruction(X86.CpuId, eax, eax); context.AppendInstruction(X86.Mov, result, reg); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { Operand result = context.Result; Operand operand1 = context.Operand1; RegisterOperand edx = new RegisterOperand(operand1.Type, GeneralPurposeRegister.EDX); RegisterOperand eax = new RegisterOperand(result.Type, GeneralPurposeRegister.EAX); context.SetInstruction(X86.Mov, edx, operand1); context.AppendInstruction(X86.In, eax, edx); context.AppendInstruction(X86.Mov, result, eax); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters) { 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(X86.Mov, edx, dest); context.AppendInstruction(X86.Mov, eax, value); context.AppendInstruction(X86.Mov, memory, eax); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { Operand dest = context.Operand1; Operand value = context.Operand2; Operand v1 = methodCompiler.CreateVirtualRegister(dest.Type); Operand v2 = methodCompiler.CreateVirtualRegister(value.Type); Operand memory = Operand.CreateMemoryAddress(context.InvokeMethod.Signature.Parameters[1].ParameterType, v1, 0); context.SetInstruction(X86.Mov, v1, dest); context.AppendInstruction(X86.Mov, v2, value); context.AppendInstruction(X86.Mov, memory, v2); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { var dest = context.Operand1; // The size will be 128 bits var v0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM0); var memDest1 = Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.Void, dest, 0); var memDest2 = Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.Void, dest, 16); context.SetInstruction(X86.PXor, InstructionSize.Size128, v0, v0, v0); context.AppendInstruction(X86.MovUPS, InstructionSize.Size128, memDest1, v0); context.AppendInstruction(X86.MovUPS, InstructionSize.Size128, memDest2, v0); }
/// <summary> /// Adds the prologue instructions. /// </summary> /// <param name="context">The context.</param> private void AddPrologueInstructions(Context context) { Operand ebp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBP); Operand esp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); context.SetInstruction(X86.Push, null, ebp); context.AppendInstruction(X86.Mov, ebp, esp); if (MethodCompiler.StackSize != 0) { context.AppendInstruction(X86.Sub, esp, esp, Operand.CreateConstant(TypeSystem, -MethodCompiler.StackSize)); } }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { var dest = context.Operand1; var src = context.Operand2; var v0 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void); var v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void); var zero = Operand.CreateConstant(methodCompiler.TypeSystem, 0); var offset16 = Operand.CreateConstant(methodCompiler.TypeSystem, 16); context.SetInstruction(X86.MovupsLoad, InstructionSize.Size128, v0, dest, zero); context.AppendInstruction(X86.MovupsLoad, InstructionSize.Size128, v1, dest, offset16); context.AppendInstruction(X86.MovupsStore, InstructionSize.Size128, null, dest, zero, v0); context.AppendInstruction(X86.MovupsStore, InstructionSize.Size128, null, dest, offset16, v1); }
/// <summary> /// Adds the epilogue instructions. /// </summary> /// <param name="context">The context.</param> private void AddEpilogueInstructions(Context context) { Operand ebp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBP); Operand esp = Operand.CreateCPURegister(TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); context.Empty(); if (MethodCompiler.StackSize != 0) { context.AppendInstruction(X86.Add, esp, esp, Operand.CreateConstant(TypeSystem, -MethodCompiler.StackSize)); } context.AppendInstruction(X86.Pop, ebp); context.AppendInstruction(X86.Ret); }
public static Context CreateNewBlock(this InstructionSet instructionSet, BasicBlocks basicBlocks) { Context ctx = new Context(instructionSet); ctx.AppendInstruction(IRInstruction.BlockStart); int start = ctx.Index; ctx.AppendInstruction(IRInstruction.BlockEnd); int last = ctx.Index; BasicBlock block = basicBlocks.CreateBlockWithAutoLabel(start, last); ctx.BasicBlock = block; ctx.GotoPrevious(); return ctx; }
private void HandleSplitAnd(Context context) { Operand r8 = Operand.CreateCPURegister(context.Operand1.Type, GeneralPurposeRegister.R8); context.SetInstruction(AVR32.Mov, r8, context.Operand1); context.AppendInstruction(AVR32.And, context.Result, r8); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { var result = context.Result; var address = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.I4); context.SetInstruction(IRInstruction.Move, address, Operand.CreateUnmanagedSymbolPointer(methodCompiler.TypeSystem, Multiboot0695Stage.MultibootEBX)); context.AppendInstruction(IRInstruction.Move, result, Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.I4, address, 0)); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { var ctor = context.Operand1; var thisObject = context.Operand2; var result = context.Result; var esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Pointer, GeneralPurposeRegister.ESP); var edx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Pointer, GeneralPurposeRegister.EDX); var espMovment = Operand.CreateConstant(methodCompiler.TypeSystem, 4); context.SetInstruction(X86.Sub, esp, esp, espMovment); context.AppendInstruction(X86.Mov, edx, esp); context.AppendInstruction(X86.Mov, Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.Pointer, edx, 0), thisObject); context.AppendInstruction(X86.Call, null, ctor); context.AppendInstruction(X86.Add, esp, esp, espMovment); context.AppendInstruction(X86.Mov, result, thisObject); }
/// <summary> /// Runs the specified method compiler. /// </summary> void IMethodCompilerStage.Run() { if (methodCompiler.PlugSystem != null) if (methodCompiler.PlugSystem.GetPlugMethod(this.methodCompiler.Method) != null) return; List<StackOperand> locals = CollectLocalVariablesFromIL(); // Iterate and collect locals from all blocks foreach (BasicBlock block in basicBlocks) { CollectLocalVariables(locals, block); } // Sort all found locals OrderVariables(locals, callingConvention); // Now we assign increasing stack offsets to each variable localsSize = LayoutVariables(locals, callingConvention, callingConvention.OffsetOfFirstLocal, 1); // Layout parameters LayoutParameters(methodCompiler); // Create a prologue instruction Context prologueCtx = new Context(instructionSet, FindBlock(-1)).InsertBefore(); prologueCtx.SetInstruction(IR.Instruction.PrologueInstruction); prologueCtx.Label = -1; // Create an epilogue instruction Context epilogueCtx = new Context(instructionSet, FindBlock(Int32.MaxValue)); epilogueCtx.AppendInstruction(IR.Instruction.EpilogueInstruction); epilogueCtx.Label = Int32.MaxValue; }
/// <summary> /// Creates the ISR methods. /// </summary> private void CreateExceptionVector() { RuntimeType runtimeType = typeSystem.GetType(@"Mosa.Kernel.x86.IDT"); if (runtimeType == null) return; RuntimeMethod runtimeMethod = runtimeType.FindMethod(@"ExceptionHandler"); if (runtimeMethod == null) return; SymbolOperand exceptionMethod = SymbolOperand.FromMethod(runtimeMethod); RegisterOperand esp = new RegisterOperand(BuiltInSigType.Int32, GeneralPurposeRegister.ESP); InstructionSet instructionSet = new InstructionSet(100); Context ctx = new Context(instructionSet); // TODO - setup stack for call to the managed exception handler //1. //2. //3. Call the managed exception handler ctx.AppendInstruction(Instruction.CallInstruction, null, exceptionMethod); LinkTimeCodeGenerator.Compile(this.compiler, @"ExceptionVector", instructionSet, typeSystem); }
private static void PatchInvoke(BaseMethodCompiler methodCompiler) { // check if instance is null (if so, it's a static call to the methodPointer) MosaField methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer"); int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField); Operand methodPointerOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, methodPointerOffset); MosaField instanceField = GetField(methodCompiler.Method.DeclaringType, "instance"); int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField); Operand instanceOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, instanceOffset); var size = methodCompiler.Architecture.NativeInstructionSize; bool withReturn = (methodCompiler.Method.Signature.ReturnType != null); Context b0 = new Context(CreateMethodStructure(methodCompiler, false)); Context b1 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Context b2 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Context b3 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Operand[] vrs = new Operand[methodCompiler.Parameters.Length]; for (int i = 0; i < methodCompiler.Parameters.Length; i++) { vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type); b0.AppendInstruction(IRInstruction.Move, vrs[i], methodCompiler.Parameters[i]); } Operand thisOperand = vrs[0]; Operand opMethod = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.U4); Operand opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type); Operand opCompare = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.I4); Operand opReturn = withReturn ? methodCompiler.VirtualRegisters.Allocate(methodCompiler.Method.Signature.ReturnType) : null; Operand c0 = Operand.CreateConstant(methodCompiler.TypeSystem, 0); b0.AppendInstruction(IRInstruction.Load, size, opMethod, thisOperand, methodPointerOffsetOperand); b0.AppendInstruction(IRInstruction.Load, size, opInstance, thisOperand, instanceOffsetOperand); b0.AppendInstruction(IRInstruction.IntegerCompare, ConditionCode.Equal, opCompare, opInstance, c0); b0.AppendInstruction(IRInstruction.IntegerCompareBranch, ConditionCode.Equal, null, opCompare, c0); b0.AddBranchTarget(b2.Block); b0.AppendInstruction(IRInstruction.Jmp, b1.Block); // no instance b1.AppendInstruction(IRInstruction.Call, opReturn, opMethod); b1.InvokeMethod = methodCompiler.Method; for (int i = 1; i < methodCompiler.Parameters.Length; i++) { b1.AddOperand(vrs[i]); } if (withReturn) { b1.SetResult(0, opReturn); } b1.AppendInstruction(IRInstruction.Jmp, b3.Block); // instance b2.AppendInstruction(IRInstruction.Call, opReturn, opMethod); b2.InvokeMethod = methodCompiler.Method; b2.AddOperand(opInstance); for (int i = 1; i < methodCompiler.Parameters.Length; i++) { b2.AddOperand(vrs[i]); } if (withReturn) { b2.SetResult(0, opReturn); } b2.AppendInstruction(IRInstruction.Jmp, b3.Block); // return b3.AppendInstruction(IRInstruction.Return, methodCompiler.BasicBlocks.EpilogueBlock); if (withReturn) { b3.SetOperand(0, opReturn); } }
private static void PatchInvoke(MethodCompiler methodCompiler) { // check if instance is null (if so, it's a static call to the methodPointer) var loadInstruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.Load32 : IRInstruction.Load64; var compareInstruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.Compare32x32 : IRInstruction.Compare64x64; var branchInstruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.Branch32 : IRInstruction.Branch64; var nativeIntegerType = methodCompiler.Architecture.Is32BitPlatform ? methodCompiler.TypeSystem.BuiltIn.U4 : methodCompiler.TypeSystem.BuiltIn.U8; var methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer"); int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField); var methodPointerOffsetOperand = methodCompiler.CreateConstant(methodPointerOffset); var instanceField = GetField(methodCompiler.Method.DeclaringType, "instance"); int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField); var instanceOffsetOperand = methodCompiler.CreateConstant(instanceOffset); var size = methodCompiler.Architecture.NativeInstructionSize; bool withReturn = (methodCompiler.Method.Signature.ReturnType == null) ? false : !methodCompiler.Method.Signature.ReturnType.IsVoid; var b0 = new Context(CreateMethodStructure(methodCompiler)); var b1 = new Context(methodCompiler.BasicBlocks.CreateBlock()); var b2 = new Context(methodCompiler.BasicBlocks.CreateBlock()); var b3 = new Context(methodCompiler.BasicBlocks.CreateBlock()); var vrs = new Operand[methodCompiler.Parameters.Length]; for (int i = 0; i < methodCompiler.Parameters.Length; i++) { var type = methodCompiler.Parameters[i].Type; if (!MosaTypeLayout.CanFitInRegister(type)) { b0.AppendInstruction(IRInstruction.LoadParamCompound, vrs[i], methodCompiler.Parameters[i]); b0.MosaType = type; } else { vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type); var paramLoadInstruction = BaseMethodCompilerStage.GetLoadParameterInstruction(vrs[i].Type, methodCompiler.Architecture.Is32BitPlatform); b0.AppendInstruction(paramLoadInstruction, vrs[i], methodCompiler.Parameters[i]); b0.MosaType = type; } } var thisOperand = vrs[0]; var opMethod = methodCompiler.VirtualRegisters.Allocate(nativeIntegerType); var opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type); var opCompare = methodCompiler.VirtualRegisters.Allocate(nativeIntegerType); var opReturn = withReturn ? methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType) : null; b0.AppendInstruction(loadInstruction, opMethod, thisOperand, methodPointerOffsetOperand); b0.AppendInstruction(loadInstruction, opInstance, thisOperand, instanceOffsetOperand); b0.AppendInstruction(compareInstruction, ConditionCode.Equal, opCompare, opInstance, methodCompiler.ConstantZero); b0.AppendInstruction(branchInstruction, ConditionCode.Equal, null, opCompare, methodCompiler.ConstantZero, b2.Block); //b0.AddBranchTarget(b2.Block); b0.AppendInstruction(IRInstruction.Jmp, b1.Block); var operands = new List <Operand>(methodCompiler.Parameters.Length + 1); for (int i = 1; i < methodCompiler.Parameters.Length; i++) { operands.Add(vrs[i]); } var result = withReturn ? opReturn : null; // no instance b1.AppendInstruction(IRInstruction.CallDynamic, result, opMethod, operands); b1.InvokeMethod = methodCompiler.Method; b1.AppendInstruction(IRInstruction.Jmp, b3.Block); // instance b2.AppendInstruction(IRInstruction.CallDynamic, result, opMethod, opInstance, operands); b2.InvokeMethod = methodCompiler.Method; b2.AppendInstruction(IRInstruction.Jmp, b3.Block); // return if (opReturn != null) { var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Architecture.Is32BitPlatform); b3.AppendInstruction(setReturn, null, opReturn); } b3.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }