using System; using System.Collections.Generic; using System.Linq; using System.Text; using Cosmos.Kernel.Boot.Glue; using Indy.IL2CPU.Assembler; using Indy.IL2CPU.IL.X86.Native.CustomImplementations.System; using Indy.IL2CPU.IL.X86.Native.CustomImplementations.System.Diagnostics; using Mono.Cecil; using CPU = Indy.IL2CPU.Assembler.X86; using CPUNative = Indy.IL2CPU.Assembler.X86.Native; namespace Indy.IL2CPU.IL.X86.Native { public class NativeOpCodeMap: X86.X86OpCodeMap { internal static NativeOpCodeMap Instance; public NativeOpCodeMap() { Instance = this; } public MethodDefinition GetGlueMethod(GlueMethodTypeEnum aMethodType) { CheckGlueMethod(); if (!mGlueMethods.ContainsKey(aMethodType)) { throw new Exception("GlueMethod '" + aMethodType.ToString() + "' not implemented!"); } MethodDefinition xResult = mGlueMethods[aMethodType]; Engine.QueueMethod(xResult); return xResult; } public MethodDefinition GetGluePlaceholderMethod(GluePlaceholderMethodTypeEnum aMethodType) { CheckGluePlaceholderMethod(); if (!mGluePlaceholderMethods.ContainsKey(aMethodType)) { throw new Exception("GluePlaceholderMethod '" + aMethodType.ToString() + "' not implemented!"); } return mGluePlaceholderMethods[aMethodType]; } public FieldDefinition GetGlueField(GlueFieldTypeEnum aFieldType) { CheckGlueField(); if (!mGlueFields.ContainsKey(aFieldType)) { throw new Exception("GlueField '" + aFieldType.ToString() + "' not found!"); } return mGlueFields[aFieldType]; } protected override Type GetCustomMethodImplementationOp() { return typeof(NativeCustomMethodImplementationOp); } protected override Type GetMethodFooterOp() { return typeof(NativeMethodFooterOp); } protected override Type GetMainEntryPointOp() { return typeof(NativeMainEntryMethodOp); } protected override Type GetMethodHeaderOp() { return typeof(NativeMethodHeaderOp); } private SortedList mGlueMethods; private SortedList mGluePlaceholderMethods; private SortedList mGlueFields; private void CheckGlueMethod() { if (mGlueMethods != null) { return; } mGlueMethods = new SortedList(); AssemblyDefinition xCrawledAsm = Engine.GetCrawledAssembly(); foreach (ModuleDefinition xModule in xCrawledAsm.Modules) { foreach (TypeDefinition xType in xModule.Types) { foreach (MethodDefinition xMethod in xType.Methods) { CustomAttribute xAttrib = (from item in xMethod.CustomAttributes.Cast() where item.Constructor.DeclaringType.FullName == typeof(GlueMethodAttribute).FullName select item).FirstOrDefault(); if (xAttrib == null) { continue; } if (!xAttrib.Resolved) { if (!xAttrib.Resolve()) { throw new Exception("Couldn't resolve attribute on method '" + xMethod.GetFullName()); } } mGlueMethods.Add((GlueMethodTypeEnum)xAttrib.Properties["MethodType"], xMethod); } } } } private void CheckGluePlaceholderMethod() { if (mGluePlaceholderMethods != null) { return; } mGluePlaceholderMethods = new SortedList(); AssemblyDefinition xCrawledAsm = Engine.GetCrawledAssembly(); foreach (ModuleDefinition xModule in xCrawledAsm.Modules) { foreach (TypeDefinition xType in xModule.Types) { foreach (MethodDefinition xMethod in xType.Methods) { CustomAttribute xAttrib = (from item in xMethod.CustomAttributes.Cast() where item.Constructor.DeclaringType.FullName == typeof(GluePlaceholderMethodAttribute).FullName select item).FirstOrDefault(); if (xAttrib == null) { continue; } if (!xAttrib.Resolved) { if (!xAttrib.Resolve()) { throw new Exception("Couldn't resolve attribute on method '" + xMethod.GetFullName()); } } mGluePlaceholderMethods.Add((GluePlaceholderMethodTypeEnum)xAttrib.Properties["MethodType"], xMethod); } } } } private void CheckGlueField() { if (mGlueFields != null) { return; } mGlueFields = new SortedList(); AssemblyDefinition xCrawledAsm = Engine.GetCrawledAssembly(); foreach (ModuleDefinition xModule in xCrawledAsm.Modules) { foreach (TypeDefinition xType in xModule.Types) { foreach (FieldDefinition xFieldDefinition in xType.Fields) { CustomAttribute xAttrib = (from item in xFieldDefinition.CustomAttributes.Cast() where item.Constructor.DeclaringType.FullName == typeof(GlueFieldAttribute).FullName select item).FirstOrDefault(); if (xAttrib == null) { continue; } if (!xAttrib.Resolved) { if (!xAttrib.Resolve()) { throw new Exception("Couldn't resolve attribute on method '" + xFieldDefinition.GetFullName()); } } if (mGlueFields.ContainsKey((GlueFieldTypeEnum)xAttrib.Properties["FieldType"])) { System.Diagnostics.Debugger.Break(); throw new Exception("GlueField of type '" + ((GlueFieldTypeEnum)xAttrib.Properties["FieldType"]).ToString() + "' already found!"); } mGlueFields.Add((GlueFieldTypeEnum)xAttrib.Properties["FieldType"], xFieldDefinition); } } } } public override MethodReference GetCustomMethodImplementation(string aOrigMethodName, bool aInMetalMode) { switch (aOrigMethodName) { case "System_Void___System_Console_Clear____": { return ConsoleImplRefs.ClearRef; } case "System_Void___System_Console_WriteLine___System_String___": { return ConsoleImplRefs.WriteLineRef; } case "System_Void___System_Console_Write___System_String___": { return ConsoleImplRefs.Write_string_Ref; } case "System_Void___System_Console_Write___System_Char___": { return ConsoleImplRefs.Write_char_Ref; } case "System_Void___System_Diagnostics_Debug_WriteLine___System_String___": { return GetGlueMethod(GlueMethodTypeEnum.Debug_WriteLine); } case "System_Void___System_Diagnostics_Debug_Write___System_String___": { return GetGlueMethod(GlueMethodTypeEnum.Debug_Write); } case "System_Void___System_Diagnostics_Debug_WriteLineIf___System_Boolean__System_String___": { return DebugImplRefs.WriteLineIfRef; } case "System_Void___Indy_IL2CPU_RuntimeEngine_InitializeEngine____": { return RuntimeEngineImplRefs.InitializeEngineRef; } case "System_Void___Indy_IL2CPU_RuntimeEngine_FinalizeEngine____": { return RuntimeEngineImplRefs.FinalizeEngineRef; } default: return base.GetCustomMethodImplementation(aOrigMethodName, aInMetalMode); } } public override bool HasCustomAssembleImplementation(string aMethodName, bool aInMetalMode) { switch (aMethodName) { case "System_Byte___Indy_IL2CPU_IL_X86_CustomImplementations_System_StringImpl_GetByteFromChar___System_Char___": { if (aInMetalMode) { return true; } break; } case "System_Void___Indy_IL2CPU_IL_X86_Native_RuntimeEngineImpl_IDT_LoadArray____": { return true; } case "System_Void___Indy_IL2CPU_IL_X86_Native_RuntimeEngineImpl_IDT_RegisterIDT____": { return true; } case "System_Void___Indy_IL2CPU_IL_X86_Native_RuntimeEngineImpl_GDT_LoadArray____": { return true; } case "System_Void___Indy_IL2CPU_IL_X86_Native_RuntimeEngineImpl_GDT_RegisterGDT____": { return true; } case "System_Void___Indy_IL2CPU_RuntimeEngine_Heap_Initialize____": { return true; } case "System_Void___System_Diagnostics_Debugger_Break____": { return true; } case "System_Void___Indy_IL2CPU_IL_X86_Native_RuntimeEngineImpl_IO_WriteToPort___System_UInt16__System_Byte__": { return true; } case "System_Byte___Indy_IL2CPU_IL_X86_Native_RuntimeEngineImpl_IO_ReadFromPort___System_UInt16__": { return true; } case "System_Void___Cosmos_Kernel_ConsoleDrv_TestIDT____": { return true; } default: { CheckGluePlaceholderMethod(); GluePlaceholderMethodTypeEnum? xMethodType = null; return (from item in mGluePlaceholderMethods.Keys where new Label(mGluePlaceholderMethods[item]).Name == aMethodName select item).Count() > 0; } } return base.HasCustomAssembleImplementation(aMethodName, aInMetalMode); } public override void DoCustomAssembleImplementation(string aMethodName, bool aInMetalMode, Assembler.Assembler aAssembler, MethodInformation aMethodInfo) { switch (aMethodName) { case "System_Byte___Indy_IL2CPU_IL_X86_CustomImplementations_System_StringImpl_GetByteFromChar___System_Char___": { if (aInMetalMode) { DoAssemble_String_GetByteFromChar(aAssembler, aMethodInfo); return; } break; } case "System_Void___Indy_IL2CPU_RuntimeEngine_Heap_Initialize____": { return; } case "System_Void___System_Diagnostics_Debugger_Break____": { //aAssembler.Add(new Literal("xchg bx, bx")); return; } case "System_Void___Cosmos_Kernel_ConsoleDrv_TestIDT____": { aAssembler.Add(new Literal("xchg bx, bx")); aAssembler.Add(new Literal("int 3")); break; } default: { CheckGluePlaceholderMethod(); GluePlaceholderMethodTypeEnum? xMethodType = null; foreach (GluePlaceholderMethodTypeEnum xTheMethodType in mGluePlaceholderMethods.Keys) { if (new Label(mGluePlaceholderMethods[xTheMethodType]).Name == aMethodName) { xMethodType = xTheMethodType; break; } } if (xMethodType != null) { AssembleGluePlaceholderMethod(xMethodType.Value, aAssembler, aMethodInfo); } break; } } base.DoCustomAssembleImplementation(aMethodName, aInMetalMode, aAssembler, aMethodInfo); } private void AssembleGluePlaceholderMethod(GluePlaceholderMethodTypeEnum aMethodType, Assembler.Assembler aAssembler, MethodInformation aMethodInfo) { switch (aMethodType) { case GluePlaceholderMethodTypeEnum.GDT_LoadArray: { FieldDefinition xFieldDef = GetGlueField(GlueFieldTypeEnum.GDT_Array); string xFieldName = Assembler.DataMember.GetStaticFieldName(xFieldDef); string xFieldData = "0,0,0,0,2,0,0,0,1,0,0,0"; for (int i = 0; i < 1; i++) { xFieldData += ",0,0,0,0,0,0,0,0"; } aAssembler.DataMembers.RemoveAll(delegate(DataMember aItem) { return aItem.Name == xFieldName; }); aAssembler.DataMembers.Add(new DataMember(xFieldName, "dd", xFieldName)); aAssembler.DataMembers.Add(new DataMember(xFieldName + "___Contents", "db", xFieldData)); xFieldDef = GetGlueField(GlueFieldTypeEnum.GDT_Pointer); string xPointerFieldName; Engine.QueueStaticField(xFieldDef, out xPointerFieldName); aAssembler.Add(new CPU.Move("eax", xPointerFieldName)); aAssembler.Add(new CPU.Move("word [eax]", "0x" + ((8 * 1) - 1).ToString("X"))); aAssembler.Add(new CPU.Move("ecx", xFieldName)); aAssembler.Add(new CPU.Add("ecx", "0xC")); aAssembler.Add(new CPU.Move("dword [eax + 2]", "ecx")); break; } case GluePlaceholderMethodTypeEnum.GDT_Register: { FieldDefinition xFieldDef = GetGlueField(GlueFieldTypeEnum.GDT_Pointer); string xPointerFieldName; Engine.QueueStaticField(xFieldDef, out xPointerFieldName); aAssembler.Add(new CPU.Move("eax", xPointerFieldName)); aAssembler.Add(new CPUNative.Cli()); aAssembler.Add(new Literal("XCHG BX, BX ")); aAssembler.Add(new CPUNative.Lgdt("eax")); aAssembler.Add(new Literal("use32")); aAssembler.Add(new CPU.JumpAlways("flush____gdt______table__part1")); aAssembler.Add(new Label("flush____gdt______table__part1")); aAssembler.Add(new CPU.Move("eax", "0x0")); aAssembler.Add(new CPU.Move("ds", "ax")); aAssembler.Add(new CPU.Move("es", "ax")); aAssembler.Add(new CPU.Move("fs", "ax")); aAssembler.Add(new CPU.Move("gs", "ax")); aAssembler.Add(new CPU.Move("ss", "ax")); aAssembler.Add(new CPU.JumpAlways("flush____gdt______table__part2")); aAssembler.Add(new Label("flush____gdt______table__part2")); break; } case GluePlaceholderMethodTypeEnum.IDT_LoadArray: { MethodDefinition xTheMethod = GetGlueMethod(GlueMethodTypeEnum.IDT_SetHandler); Engine.QueueMethod(xTheMethod); mIDTSetHandlerMethodName = new Label(xTheMethod).Name; FieldDefinition xFieldDef = GetGlueField(GlueFieldTypeEnum.IDT_Array); string xFieldName = Assembler.DataMember.GetStaticFieldName(xFieldDef); string xFieldData = "0,0,0,0,2,0,0,0,1,0,0,0"; for (int i = 0; i < 256; i++) { xFieldData += ",0,0,0,0,0,0,0,0"; } aAssembler.DataMembers.RemoveAll(delegate(DataMember aItem) { return aItem.Name == xFieldName; }); aAssembler.DataMembers.Add(new DataMember(xFieldName, "dd", xFieldName + "___Contents")); aAssembler.DataMembers.Add(new DataMember(xFieldName + "___Contents", "db", xFieldData)); xFieldDef = GetGlueField(GlueFieldTypeEnum.IDT_Pointer); string xPointerFieldName; Engine.QueueStaticField(xFieldDef, out xPointerFieldName); aAssembler.Add(new CPU.Move("eax", xPointerFieldName)); aAssembler.Add(new CPU.Move("word [eax]", "0x" + ((8 * 256) - 1).ToString("X"))); aAssembler.Add(new CPU.Move("ecx", xFieldName)); aAssembler.Add(new CPU.Add("ecx", "0xC")); aAssembler.Add(new CPU.Move("dword [eax + 2]", "ecx")); break; } case GluePlaceholderMethodTypeEnum.IDT_Register: { FieldDefinition xFieldDef = GetGlueField(GlueFieldTypeEnum.IDT_Pointer); string xPointerFieldName; Engine.QueueStaticField(xFieldDef, out xPointerFieldName); MethodDefinition xTheMethod = GetGlueMethod(GlueMethodTypeEnum.IDT_SetHandler); Engine.QueueMethod(xTheMethod); mIDTSetHandlerMethodName = new Label(xTheMethod).Name; aAssembler.Add(new CPU.Call("___________REGISTER___ISRS_____")); aAssembler.Add(new CPU.Move("eax", xPointerFieldName)); aAssembler.Add(new Literal("XCHG BX, BX ")); aAssembler.Add(new CPUNative.Cli()); aAssembler.Add(new CPUNative.Lidt("eax")); aAssembler.Add(new CPUNative.Sti()); GetGlueMethod(GlueMethodTypeEnum.IDT_InterruptHandler); break; } case GluePlaceholderMethodTypeEnum.IO_ReadByte: { aAssembler.Add(new CPU.Xor("eax", "eax")); IL.X86.Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0].VirtualAddresses, aMethodInfo.Arguments[0].Size); aAssembler.Add(new CPU.Pop("edx")); aAssembler.Add(new CPU.Move("eax", "0")); aAssembler.Add(new CPUNative.In("al", "dx")); aAssembler.Add(new CPU.Push("eax")); break; } case GluePlaceholderMethodTypeEnum.IO_WriteByte: { Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0].VirtualAddresses, aMethodInfo.Arguments[0].Size); aAssembler.Add(new CPU.Pop("edx")); Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[1].VirtualAddresses, aMethodInfo.Arguments[1].Size); aAssembler.Add(new CPU.Pop("eax")); aAssembler.Add(new CPUNative.Out("dx", "al")); break; } default: throw new NotImplementedException("GluePlaceholderMethod '" + aMethodType.ToString() + "' not implemented!"); } } private string mIDTSetHandlerMethodName; private static void DoAssemble_String_GetByteFromChar(Assembler.Assembler aAssembler, MethodInformation aMethodInfo) { X86.Ldarg.Ldarg(aAssembler, aMethodInfo.Arguments[0].VirtualAddresses, aMethodInfo.Arguments[0].Size); } public override void PostProcess(Indy.IL2CPU.Assembler.Assembler aAssembler) { base.PostProcess(aAssembler); return; TypeDefinition xRuntimeEngineTypeDef = Engine.GetTypeDefinition(typeof(RuntimeEngineImpl).Assembly.GetName().Name, typeof(RuntimeEngineImpl).FullName); MethodDefinition xTheMethod = GetGlueMethod(GlueMethodTypeEnum.IDT_SetHandler); Engine.QueueMethod(xTheMethod); mIDTSetHandlerMethodName = new Label(xTheMethod).Name; X86.X86MethodHeaderOp.AssembleHeader(aAssembler, "___________REGISTER___ISRS_____", new int[0]); string xInterruptHandlerLabel = new Label(GetGlueMethod(GlueMethodTypeEnum.IDT_InterruptHandler)).Name; int[] xInterruptsWithParam = new int[] { 8, 10, 11, 12, 13, 14 }; for (int i = 0; i < 256; i++) { aAssembler.Add(new CPU.Push("0x" + i.ToString("X"))); //if (i == 3) { // aAssembler.Add(new Literal("xchg bx, bx")); //} aAssembler.Add(new CPU.Push("____INTERRUPT_HANDLER___" + i)); aAssembler.Add(new CPU.Push("0x08")); aAssembler.Add(new CPU.Push("0x8E")); aAssembler.Add(new CPU.Call(mIDTSetHandlerMethodName)); } X86.X86MethodFooterOp.AssembleFooter(0, aAssembler, new int[0], 0); for (int j = 0; j < 256; j++) { aAssembler.Add(new Label("____INTERRUPT_HANDLER___" + j)); aAssembler.Add(new CPUNative.Cli()); aAssembler.Add(new CPU.Push(j.ToString())); if (!xInterruptsWithParam.Contains(j)) { aAssembler.Add(new CPU.Push("0")); } aAssembler.Add(new CPU.JumpAlways("____INTERRUPT_HANDLER___GENERIC")); } aAssembler.Add(new Label("____INTERRUPT_HANDLER___GENERIC")); aAssembler.Add(new CPUNative.Pushad()); aAssembler.Add(new CPU.Move("ax", "ds")); aAssembler.Add(new CPU.Push("eax")); aAssembler.Add(new CPU.Move("ds", "ax")); aAssembler.Add(new CPU.Move("es", "ax")); aAssembler.Add(new CPU.Move("fs", "ax")); aAssembler.Add(new CPU.Move("gs", "ax")); aAssembler.Add(new CPU.Call(xInterruptHandlerLabel)); aAssembler.Add(new CPU.Pop("ebx")); aAssembler.Add(new CPU.Move("ds", "bx")); aAssembler.Add(new CPU.Move("es", "bx")); aAssembler.Add(new CPU.Move("fs", "bx")); aAssembler.Add(new CPU.Move("gs", "bx")); aAssembler.Add(new CPUNative.Popad()); aAssembler.Add(new CPUNative.Sti()); aAssembler.Add(new CPUNative.IRet()); } } }