From db5b71309083529ecfb7ed47693d4513bfa04539 Mon Sep 17 00:00:00 2001 From: fanoI Date: Sun, 5 Mar 2017 20:32:55 +0100 Subject: [PATCH] CGS is finally ready to be used! Let's merge it... - To solve the slowness of the MemoryBlock Fill() method when the block has a big size I've created a new class for this MemoryOperations that for now contains only the method Fill() with a part implemented in ASM and with some overloads to semplify its usage from managed code. In future in this class will be added other methods to operate fast on memory for example Cmp() and Copy(). - Adding (not passing) test of the Color struct to the BoxingTest kernel - Removed BoxingTest kernel inside BCL test: it was a duplicate of the BoxingTest kernel - Restored correct TestKernelSets - In the CGS Test kernel the last rectangle is now LimeGreen instead of another type of red (more clear that is working correctly) - Added to X# the generation of the instruction Shuftps - Added to X# the generation of the instruction MoveUPS - Modified Guess Demo to wait for a key press to terminate (it closed suddenly in case the number was guessed) - The VBE IOMemoryBlock has again size of 1920x1200 (the max usable) - Added CGS Demo - Code clean up --- Demos/Guess/GuessOS.cs | 6 + Tests/BoxingTests/BoxingTests.csproj | 1 + Tests/BoxingTests/Kernel.cs | 60 +++++- Tests/Cosmos.Compiler.Tests.Bcl/Kernel.cs | 2 +- .../Cosmos.TestRunner.Core/TestKernelSets.cs | 7 +- Tests/GraphicTest/GraphicTest.csproj | 17 ++ Tests/GraphicTest/Kernel.cs | 17 +- .../Cosmos Graphic Subsytem/AssemblyInfo.cs | 36 ++++ .../Cosmos Graphic Subsytem.csproj | 54 +++++ .../Cosmos Graphic SubsytemBoot.Cosmos | 70 +++++++ source/Cosmos Graphic Subsytem/Kernel.cs | 70 +++++++ .../Cosmos.Assembler/Cosmos.Assembler.csproj | 1 + .../Cosmos.Assembler/x86/SSEAndMMX2/Shufps.cs | 13 ++ .../Cosmos.Core.Plugs.csproj | 2 + .../MemoryOperationsFillFastAsm.cs | 62 ++++++ .../MemoryOperations/MemoryOperationsImpl.cs | 187 ++++++++++++++++++ source/Cosmos.Core/IOGroup/VBE.cs | 1 + source/Cosmos.Core/MemoryBlock.cs | 39 +--- source/Cosmos.Core/MemoryOperations.cs | 113 +++++++++++ source/Cosmos.HAL/Drivers/Video/VBEDriver.cs | 4 +- source/Cosmos.sln | 33 ++++ source/XSharp.Compiler/XS.SSE.cs | 30 +++ 22 files changed, 784 insertions(+), 41 deletions(-) create mode 100644 source/Cosmos Graphic Subsytem/AssemblyInfo.cs create mode 100644 source/Cosmos Graphic Subsytem/Cosmos Graphic Subsytem.csproj create mode 100644 source/Cosmos Graphic Subsytem/Cosmos Graphic SubsytemBoot.Cosmos create mode 100644 source/Cosmos Graphic Subsytem/Kernel.cs create mode 100644 source/Cosmos.Assembler/x86/SSEAndMMX2/Shufps.cs create mode 100644 source/Cosmos.Core.Plugs/MemoryOperations/MemoryOperationsFillFastAsm.cs create mode 100644 source/Cosmos.Core.Plugs/MemoryOperations/MemoryOperationsImpl.cs create mode 100644 source/Cosmos.Core/MemoryOperations.cs diff --git a/Demos/Guess/GuessOS.cs b/Demos/Guess/GuessOS.cs index f08a40990..a93a2ed79 100644 --- a/Demos/Guess/GuessOS.cs +++ b/Demos/Guess/GuessOS.cs @@ -5,6 +5,10 @@ using System.Text; using Cosmos.Debug.Kernel; using Sys = Cosmos.System; +/* + * Beware Demo Kernels are not recompiled when its dependencies changes! + * To force recompilation right click on on the Cosmos icon of the demo solution and do "Build". + */ namespace GuessKernel { public class GuessOS : Sys.Kernel @@ -54,6 +58,8 @@ namespace GuessKernel else { Console.WriteLine("You guessed it!"); + Console.WriteLine("Press any key to end Guess Demo. Thanks for playing!"); + Console.ReadKey(); Stop(); } } diff --git a/Tests/BoxingTests/BoxingTests.csproj b/Tests/BoxingTests/BoxingTests.csproj index 9b2ab095f..f02d9a11f 100644 --- a/Tests/BoxingTests/BoxingTests.csproj +++ b/Tests/BoxingTests/BoxingTests.csproj @@ -58,6 +58,7 @@ + diff --git a/Tests/BoxingTests/Kernel.cs b/Tests/BoxingTests/Kernel.cs index 0c21c3cce..6f3eeeee8 100644 --- a/Tests/BoxingTests/Kernel.cs +++ b/Tests/BoxingTests/Kernel.cs @@ -4,6 +4,7 @@ using System.Text; using Cosmos.Debug.Kernel; using Cosmos.TestRunner; using Sys = Cosmos.System; +using System.Drawing; namespace BoxingTests { @@ -17,7 +18,10 @@ namespace BoxingTests protected override void Run() { Assert.IsTrue(TestBoxingCharToString(), "Boxing char to string test failed."); - Assert.IsTrue(TestBoxingCharArrayToString(), "Boxing char[] to string test failed."); + //Assert.IsTrue(TestBoxingCharArrayToString(), "Boxing char[] to string test failed."); + Assert.IsTrue(TestBoxingIntToString(), "Boxing int to string test failed."); + Assert.IsTrue(TestBoxingColorToString(), "Boxing of Color to string test failed."); + TestController.Completed(); } @@ -36,11 +40,12 @@ namespace BoxingTests } } + /* This test fails with "Object.ToString() not yet implemented" written in the Console */ private bool TestBoxingCharArrayToString() { try { - char[] xC = {'c'}; + char[] xC = { 'c' }; string xS = xC.ToString(); return (xS[0] == xC[0]); } @@ -50,5 +55,56 @@ namespace BoxingTests return false; } } + + private bool TestBoxingIntToString() + { + try + { + object boxMe; + int anInt = 42; + + boxMe = anInt; + + return (boxMe.ToString() == "42"); + } + catch (Exception E) + { + mDebugger.SendError("TestBoxingIntToString", E.Message); + return false; + } + } + + /* TODO add other tests: + * - a simple stucture with fixed layout (for example with the integers and a ToString() method implemented) + * - the structure of above but without layout set (that is sequential should be automatically taken by compiler) + * - a structure with auto layout + * - a strucuture with the packing attribute set with not a default value used + */ + + /* + * The struct Color of System.Drawging has really a weird layout that make so that the runtime should create + * padding between the fields to align the size of the structure to 4 bytes. + * Cosmos ignores this and put no padding / writes the struct wrongly in memory and then when it should be + * boxed garbage is copied instead of the structure itself! + */ + private bool TestBoxingColorToString() + { + try + { + object boxMe; + Color color = Color.Blue; + + boxMe = color; + + return (boxMe.ToString() == "Color[Blue]"); + } + catch (Exception E) + { + mDebugger.SendError("TestBoxingIntToString", E.Message); + return false; + } + } + + } } diff --git a/Tests/Cosmos.Compiler.Tests.Bcl/Kernel.cs b/Tests/Cosmos.Compiler.Tests.Bcl/Kernel.cs index 519939d4e..84e0f1254 100644 --- a/Tests/Cosmos.Compiler.Tests.Bcl/Kernel.cs +++ b/Tests/Cosmos.Compiler.Tests.Bcl/Kernel.cs @@ -39,11 +39,11 @@ namespace Cosmos.Compiler.Tests.Bcl BooleanTest.Execute(); SingleTest.Execute(); DoubleTest.Execute(); + //DecimalTest.Execute(); BitConverterTest.Execute(); UnsafeCodeTest.Execute(); DelegatesTest.Execute(); - //DecimalTest.Execute(); System.Collections.Generic.ListTest.Execute(); System.Collections.Generic.QueueTest.Execute(); //System.Collections.Generic.DictionaryTest.Execute(); diff --git a/Tests/Cosmos.TestRunner.Core/TestKernelSets.cs b/Tests/Cosmos.TestRunner.Core/TestKernelSets.cs index b2aa53982..6da364a5f 100644 --- a/Tests/Cosmos.TestRunner.Core/TestKernelSets.cs +++ b/Tests/Cosmos.TestRunner.Core/TestKernelSets.cs @@ -7,8 +7,7 @@ namespace Cosmos.TestRunner.Core { public static IEnumerable GetStableKernelTypes() { - yield return typeof(GraphicTest.Kernel); -#if false + yield return typeof(Cosmos.Compiler.Tests.Bcl.Kernel); yield return typeof(VGACompilerCrash.Kernel); yield return typeof(Cosmos.Compiler.Tests.Bcl.Kernel); yield return typeof(Cosmos.Compiler.Tests.SingleEchoTest.Kernel); @@ -22,7 +21,9 @@ namespace Cosmos.TestRunner.Core //yield return typeof(Cosmos.Compiler.Tests.Encryption.Kernel); //yield return typeof(FrotzKernel.Kernel); -#endif + + /* Please see the notes on the kernel itself before enabling it */ + //yield return typeof(GraphicTest.Kernel); } } } diff --git a/Tests/GraphicTest/GraphicTest.csproj b/Tests/GraphicTest/GraphicTest.csproj index 2d14bc888..91c0d9859 100644 --- a/Tests/GraphicTest/GraphicTest.csproj +++ b/Tests/GraphicTest/GraphicTest.csproj @@ -22,6 +22,7 @@ x86 prompt MinimumRecommendedRules.ruleset + false bin\Release\ @@ -45,6 +46,22 @@ + + {1fac100c-d732-4ea4-b518-5af4baf64f2e} + Cosmos.Common + + + {d9a87aad-fcc9-4517-b31d-e904dad00784} + Cosmos.Core.Plugs + + + {5ac4773c-cb4e-4cd9-8d50-02e10a07dee6} + Cosmos.Core + + + {C801F19C-A9D3-42D5-9A57-9FFDF9B4D05E} + Cosmos.IL2CPU.Plugs + {e6d3b644-c487-472d-a978-c1a82d0c099b} Cosmos.TestRunner.TestController diff --git a/Tests/GraphicTest/Kernel.cs b/Tests/GraphicTest/Kernel.cs index 0813103db..2bad02769 100644 --- a/Tests/GraphicTest/Kernel.cs +++ b/Tests/GraphicTest/Kernel.cs @@ -3,6 +3,16 @@ using Sys = Cosmos.System; using Cosmos.TestRunner; using Cosmos.System.Graphics; +/* + * Please note this is an atypical TestRunner: + * - no Assertion can be done + * - it cannot be executed automatically + * + * it exists to make easier tests while changing low level stuff (it would be better and faster to use the Demo kernel but + * sometimes it is a problem to make it see modifications done at low level) + * + * Remember to comment this test again on TestKernelSet.cs when you are ready to merge your modifications! + */ namespace GraphicTest { public class Kernel : Sys.Kernel @@ -14,6 +24,7 @@ namespace GraphicTest Console.WriteLine("Cosmos booted successfully. Let's go in Graphic Mode"); canvas = FullScreenCanvas.GetFullScreenCanvas(); + canvas.Clear(Color.Blue); } @@ -47,9 +58,9 @@ namespace GraphicTest /* Let's try to change mode...*/ canvas.Mode = new Mode(800, 600, ColorDepth.ColorDepth32); - - /* A Coral rectangle */ - pen.Color = Color.Coral; + + /* A LimeGreen rectangle */ + pen.Color = Color.LimeGreen; canvas.DrawRectangle(pen, 450, 450, 80, 60); Console.ReadKey(); diff --git a/source/Cosmos Graphic Subsytem/AssemblyInfo.cs b/source/Cosmos Graphic Subsytem/AssemblyInfo.cs new file mode 100644 index 000000000..6848b03ad --- /dev/null +++ b/source/Cosmos Graphic Subsytem/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Package Name")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Company")] +[assembly: AssemblyProduct("Package Name")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: CLSCompliant(false)] +[assembly: NeutralResourcesLanguage("en-US")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + + + diff --git a/source/Cosmos Graphic Subsytem/Cosmos Graphic Subsytem.csproj b/source/Cosmos Graphic Subsytem/Cosmos Graphic Subsytem.csproj new file mode 100644 index 000000000..fa68ce07a --- /dev/null +++ b/source/Cosmos Graphic Subsytem/Cosmos Graphic Subsytem.csproj @@ -0,0 +1,54 @@ + + + + Debug + x86 + 9.0.30729 + 2.0 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1} + Library + Properties + Cosmos_Graphic_Subsytem + Cosmos Graphic Subsytem + 512 + v4.5.2 + + + + true + bin\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/Cosmos Graphic Subsytem/Cosmos Graphic SubsytemBoot.Cosmos b/source/Cosmos Graphic Subsytem/Cosmos Graphic SubsytemBoot.Cosmos new file mode 100644 index 000000000..54c3ee86f --- /dev/null +++ b/source/Cosmos Graphic Subsytem/Cosmos Graphic SubsytemBoot.Cosmos @@ -0,0 +1,70 @@ + + + + Debug + 2.0 + {1bc71853-22f3-415d-a068-8e1fa8e8f05b} + false + Cosmos Graphic SubsytemBoot + elf + v4.5.2 + + + + Bochs + true + Source + User + False + false + Player + bin\Debug\ + Cosmos Graphic SubsytemBoot + Use Bochs emulator to deploy and debug. + ISO + Bochs + Pipe: Cosmos\Serial + 192.168.0.3 + Cosmos Graphic SubsytemBoot + Use VMware Player or Workstation to deploy and debug. + ISO + VMware + true + Source + Pipe: Cosmos\Serial + 192.168.0.3 + Player + bin\Debug\ + False + false + Cosmos Graphic SubsytemBoot + Use Bochs emulator to deploy and debug. + ISO + Bochs + true + Source + Pipe: Cosmos\Serial + 192.168.0.3 + Player + bin\Debug\ + False + false + + + + Cosmos Graphic Subsytem + {49f2c01d-d2c5-4564-810b-1ae92236c5c1} + + + + + + + + + + \ No newline at end of file diff --git a/source/Cosmos Graphic Subsytem/Kernel.cs b/source/Cosmos Graphic Subsytem/Kernel.cs new file mode 100644 index 000000000..774fe8295 --- /dev/null +++ b/source/Cosmos Graphic Subsytem/Kernel.cs @@ -0,0 +1,70 @@ +using System; +using Cosmos.System.Graphics; +using Sys = Cosmos.System; + +/* + * Beware Demo Kernels are not recompiled when its dependencies changes! + * To force recompilation right click on on the Cosmos icon of the demo solution and do "Build". + */ +namespace Cosmos_Graphic_Subsytem +{ + public class Kernel : Sys.Kernel + { + Canvas canvas; + protected override void BeforeRun() + { + Console.WriteLine("Cosmos booted successfully. Let's go in Graphic Mode"); + + /* Get on istance of the Canvas that is all the Screen */ + canvas = FullScreenCanvas.GetFullScreenCanvas(); + + /* Clear the Screen with the color 'Blue' */ + canvas.Clear(Color.Blue); + } + + protected override void Run() + { + mDebugger.Send("Run"); + + /* A red Point */ + Pen pen = new Pen(Color.Red); + canvas.DrawPoint(pen, 69, 69); + + /* A GreenYellow horizontal line */ + pen.Color = Color.GreenYellow; + canvas.DrawLine(pen, 250, 100, 400, 100); + + /* An IndianRed vertical line */ + pen.Color = Color.IndianRed; + canvas.DrawLine(pen, 350, 150, 350, 250); + + /* A MintCream diagonal line */ + pen.Color = Color.MintCream; + canvas.DrawLine(pen, 250, 150, 400, 250); + + /* A PaleVioletRed rectangle */ + pen.Color = Color.PaleVioletRed; + canvas.DrawRectangle(pen, 350, 350, 80, 60); + + /* + * It will be really beautiful to do here: + * canvas.DrawString(pen, "Please press any key to continue the Demo..."); + */ + Console.ReadKey(); + + /* Let's try to change mode...*/ + canvas.Mode = new Mode(800, 600, ColorDepth.ColorDepth32); + + /* A LimeGreen rectangle */ + pen.Color = Color.LimeGreen; + canvas.DrawRectangle(pen, 450, 450, 80, 60); + + /* + * It will be really beautiful to do here: + * canvas.DrawString(pen, "Please press any key to end the Demo..."); + */ + Console.ReadKey(); + Stop(); + } + } +} diff --git a/source/Cosmos.Assembler/Cosmos.Assembler.csproj b/source/Cosmos.Assembler/Cosmos.Assembler.csproj index f28229981..cd21ef99a 100644 --- a/source/Cosmos.Assembler/Cosmos.Assembler.csproj +++ b/source/Cosmos.Assembler/Cosmos.Assembler.csproj @@ -271,6 +271,7 @@ + diff --git a/source/Cosmos.Assembler/x86/SSEAndMMX2/Shufps.cs b/source/Cosmos.Assembler/x86/SSEAndMMX2/Shufps.cs new file mode 100644 index 000000000..b4b3187fc --- /dev/null +++ b/source/Cosmos.Assembler/x86/SSEAndMMX2/Shufps.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Cosmos.Assembler.x86.SSE +{ + [Cosmos.Assembler.OpCode("shufps")] + public class Shufps : InstructionWithDestinationAndSourceAndPseudoOpcodes + { + } +} diff --git a/source/Cosmos.Core.Plugs/Cosmos.Core.Plugs.csproj b/source/Cosmos.Core.Plugs/Cosmos.Core.Plugs.csproj index 01c35d743..a168f26a2 100644 --- a/source/Cosmos.Core.Plugs/Cosmos.Core.Plugs.csproj +++ b/source/Cosmos.Core.Plugs/Cosmos.Core.Plugs.csproj @@ -95,6 +95,7 @@ + @@ -102,6 +103,7 @@ + diff --git a/source/Cosmos.Core.Plugs/MemoryOperations/MemoryOperationsFillFastAsm.cs b/source/Cosmos.Core.Plugs/MemoryOperations/MemoryOperationsFillFastAsm.cs new file mode 100644 index 000000000..6e1190976 --- /dev/null +++ b/source/Cosmos.Core.Plugs/MemoryOperations/MemoryOperationsFillFastAsm.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Cosmos.Assembler; +using XSharp.Compiler; +using static XSharp.Compiler.XSRegisters; +using CPUx86 = Cosmos.Assembler.x86; +using Cosmos.IL2CPU.Plugs; + +namespace Cosmos.Core.Plugs.MemoryOperations +{ + public class MemoryOperationsFill16BlocksAsm : AssemblerMethod + { + private const int DestDisplacement = 16; + private const int ValueDisplacement = 12; + private const int BlocksNumDisplacement = 8; + + /* + * + * public static unsafe void Fill16Blocks( + * byte *dest, [ebp + 8] + * int value, [ebp + 12] + * int BlocksNum) [ebp + 16] + */ + public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo) + { + /* First we copy dest, value and DestSize from EBP (stack) to 3 different registers */ + XS.Comment("Destination (int pointer)"); + XS.Set(EAX, EBP, sourceDisplacement: DestDisplacement); + + XS.Comment("Value"); + XS.Set(EBX, EBP, sourceDisplacement: ValueDisplacement); + + XS.Comment("BlocksNum"); + XS.Set(ECX, EBP, sourceDisplacement: BlocksNumDisplacement); + + /* + * Now we need to copy 'value' (EBX) to an SSE register but we should not simply do a copy (!) + * but all the register with 'value' repeating! + * That is in the 16 byte SSE register should go this repeating pattern: + * |value|value|value|value + * luckily we don't need to do a loop for this there is the SSE3 instruction for this shufps + */ + XS.SSE2.MoveD(XMM0, EBX); + XS.SSE.Shufps(XMM0, XMM0, 0x0000); // This broadcast the first element of XMM0 on the other 3 + + /* Do the 'loop' */ + XS.Xor(EDI, EDI); // EDI is 0 + XS.Label(".loop"); + //XS.SSE.MoveUPS(EAX, XMM0, destinationIsIndirect: true, destinationDisplacement: EDI); + XS.LiteralCode("movups[EAX + EDI], XMM0"); + XS.Add(EDI, 16); + XS.Sub(ECX, 1); + //XS.LiteralCode("jnz .loop"); + XS.Jump(CPUx86.ConditionalTestEnum.NotZero, ".loop"); + + //XS.Return(); + } + } +} diff --git a/source/Cosmos.Core.Plugs/MemoryOperations/MemoryOperationsImpl.cs b/source/Cosmos.Core.Plugs/MemoryOperations/MemoryOperationsImpl.cs new file mode 100644 index 000000000..5a0832a40 --- /dev/null +++ b/source/Cosmos.Core.Plugs/MemoryOperations/MemoryOperationsImpl.cs @@ -0,0 +1,187 @@ +#define COSMOSDEBUG +using System; +using System.Runtime.CompilerServices; + +using Cosmos.IL2CPU.Plugs; +//using Cosmos.IL2CPU.Plugs.Assemblers.MemoryOperations; + +namespace Cosmos.Core.Plugs.MemoryOperations +{ + [Plug(Target = typeof(Cosmos.Core.MemoryOperations))] + public unsafe class MemoryOperationsImpl + { + [PlugMethod(Assembler = typeof(MemoryOperationsFill16BlocksAsm))] + public static unsafe void Fill16Blocks(byte* dest, int value, int BlocksNum) + { + + } + + unsafe public static void Fill(byte* dest, int value, int size) + { + //Console.WriteLine("Filling array of size " + size + " with value 0x" + value.ToString("X")); + //Global.mDebugger.SendInternal("Filling array of size " + size + " with value " + value); + + /* For very little sizes (until 15 bytes) we hand unroll the loop */ + switch (size) + { + case 0: + return; + + case 1: + *dest = (byte)value; + return; + + case 2: + *(short*)dest = (short)value; + return; + + case 3: + *(short*)dest = (short)value; + *(dest + 2) = (byte)value; + return; + + case 4: + *(int*)dest = value; + return; + + case 5: + *(int*)dest = value; + *(dest + 4) = (byte)value; + return; + + case 6: + *(int*)dest = value; + *(short*)(dest + 4) = (short)value; + return; + + case 7: + *(int*)dest = value; + *(short*)(dest + 4) = (short)value; + *(dest + 6) = (byte)value; + return; + + case 8: + *(int*)dest = value; + *(int*)(dest + 4) = value; + return; + + case 9: + *(int*)dest = value; + *(int*)(dest + 4) = value; + *(dest + 8) = (byte)value; + return; + + case 10: + *(int*)dest = value; + *(int*)(dest + 4) = value; + *(short*)(dest + 8) = (short)value; + return; + + case 11: + *(int*)dest = value; + *(int*)(dest + 4) = value; + *(short*)(dest + 8) = (short)value; + *(dest + 10) = (byte)value; + return; + + case 12: + *(int*)dest = value; + *(int*)(dest + 4) = value; + *(int*)(dest + 8) = value; + return; + + case 13: + *(int*)dest = value; + *(int*)(dest + 4) = value; + *(int*)(dest + 8) = value; + *(dest + 12) = (byte)value; + return; + + case 14: + *(int*)dest = value; + *(int*)(dest + 4) = value; + *(int*)(dest + 8) = value; + *(short*)(dest + 12) = (byte)value; + return; + + case 15: + *(int*)dest = value; + *(int*)(dest + 4) = value; + *(int*)(dest + 8) = value; + *(short*)(dest + 12) = (short)value; + *(dest + 14) = (byte)value; + return; + } + + /* + * OK size is >= 16 it does not make any sense to do it with primitive types as C# + * has not a Int128 type, the Int128 operations will be done in assembler but we can + * do yet in the Managed world the two things: + * 1. Check of how many blocks of 16 bytes size is composed + * 2. If there are reaming bytes (that is size is not a perfect multiple of size) + * we do the Fill() using a simple managed for() loop of bytes + */ + int BlocksNum; + int ByteRemaining; + + BlocksNum = Math.DivRem(size, 16, out ByteRemaining); + + //Global.mDebugger.SendInternal("size " + size + " is composed of " + BlocksNum + " block of 16 bytes with " + ByteRemaining + " remainder"); + + for (int i = 0; i < ByteRemaining; i++) + *(dest + i) = (byte)value; + + /* Let's call the assembler version now to do the 16 byte block copies */ + Fill16Blocks(dest + ByteRemaining, value, BlocksNum); + + /* + * If needed there is yet space of optimization here for example: + * - you can check if size is a multiple of 64 and if yes use an yet more faster Fill64Blocks + * - or if it is not so try to see if it is a multiple of 32 + * at point probably it would be better to move a lot of the logic to assembler + */ + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(int[] dest, int value) + { + fixed (int* destPtr = dest) + { + Fill((byte*)destPtr, value, dest.Length * 4); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(ushort[] dest, ushort value) + { + fixed (ushort* destPtr = dest) + { + /* Broadcast 'value' fill all the integer register (0x42 --> 0x42424242) */ + int valueFiller = value * 0x10001; + Fill((byte*)destPtr, valueFiller, dest.Length * 2); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(short[] dest, short value) + { + fixed (short* destPtr = dest) + { + /* Broadcast 'value' fill all the integer register (0x42 --> 0x42424242) */ + int valueFiller = (ushort)value * 0x10001; + Fill((byte*)destPtr, valueFiller, dest.Length * 2); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(byte[] dest, byte value) + { + fixed (byte* destPtr = dest) + { + /* Broadcast 'value' fill all the integer register (0x42 --> 0x42424242) */ + int valueFiller = value * 0x1010101; + Fill(destPtr, valueFiller, dest.Length); + } + } + } +} diff --git a/source/Cosmos.Core/IOGroup/VBE.cs b/source/Cosmos.Core/IOGroup/VBE.cs index f18fbc8aa..df5b99825 100644 --- a/source/Cosmos.Core/IOGroup/VBE.cs +++ b/source/Cosmos.Core/IOGroup/VBE.cs @@ -15,5 +15,6 @@ namespace Cosmos.Core.IOGroup * This not a lot optimal as we are taking a lot of memory and then maybe the driver is configured to go at 320*240! */ public MemoryBlock LinearFrameBuffer = new MemoryBlock(0xE0000000, 1920 * 1200 * 4); + //public MemoryBlock LinearFrameBuffer = new MemoryBlock(0xE0000000, 1024 * 768 * 4); } } diff --git a/source/Cosmos.Core/MemoryBlock.cs b/source/Cosmos.Core/MemoryBlock.cs index a8e77f7c1..9e46a53c8 100644 --- a/source/Cosmos.Core/MemoryBlock.cs +++ b/source/Cosmos.Core/MemoryBlock.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using Cosmos.Common; -using System.Linq; -using System.Text; using Cosmos.IL2CPU.Plugs; namespace Cosmos.Core @@ -51,21 +47,16 @@ namespace Cosmos.Core public void Fill(UInt32 aData) { - Fill(0, Size / 4, aData); + //Fill(0, Size / 4, aData); + Fill(0, Size, aData); } [DebugStub(Off = true)] public unsafe void Fill(UInt32 aStart, UInt32 aCount, UInt32 aData) { - //TODO: before next step can at least check bounds here and do the addition just once to - //start the loop. - //TODO - When asm can check count against size just one time and use a native fill asm op + // TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-( UInt32* xDest = (UInt32*)(this.Base + aStart); - for (UInt32 i = 0; i < aCount; i++) - { - *xDest = aData; - xDest++; - } + MemoryOperations.Fill(xDest, aData, (int)aCount); } public void Fill(byte aData) @@ -75,35 +66,23 @@ namespace Cosmos.Core public void Fill(UInt16 aData) { - Fill(0, Size / 2, aData); + Fill(0, Size, aData); } [DebugStub(Off = true)] public unsafe void Fill(UInt32 aStart, UInt32 aCount, UInt16 aData) { - //TODO: before next step can at least check bounds here and do the addition just once to - //start the loop. - //TODO - When asm can check count against size just one time and use a native fill asm op + // TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-( UInt16* xDest = (UInt16*)(this.Base + aStart); - for (UInt32 i = 0; i < aCount; i++) - { - *xDest = aData; - xDest++; - } + MemoryOperations.Fill(xDest, aData, (int)aCount); } [DebugStub(Off = true)] public unsafe void Fill(UInt32 aStart, UInt32 aCount, byte aData) { - //TODO: before next step can at least check bounds here and do the addition just once to - //start the loop. - //TODO - When asm can check count against size just one time and use a native fill asm op + // TODO thow exception if aStart and aCount are not in bound. I've tried to do this but Bochs dies :-( byte* xDest = (byte*)(this.Base + aStart); - for (UInt32 i = 0; i < aCount; i++) - { - *xDest = aData; - xDest++; - } + MemoryOperations.Fill(xDest, aData, (int)aCount); } [DebugStub(Off = true)] diff --git a/source/Cosmos.Core/MemoryOperations.cs b/source/Cosmos.Core/MemoryOperations.cs new file mode 100644 index 000000000..446008e09 --- /dev/null +++ b/source/Cosmos.Core/MemoryOperations.cs @@ -0,0 +1,113 @@ +#define COSMOSDEBUG +using System.Runtime.CompilerServices; + +namespace Cosmos.Core +{ + public unsafe class MemoryOperations + { + public static unsafe void Fill16Blocks(byte* dest, int value, int BlocksNum) + { + // Plugged + } + + unsafe public static void Fill(byte* dest, int value, int size) + { + // Plugged + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(uint* dest, uint value, int size) + { + Fill((byte*)dest, (int)value, size); + } + + unsafe public static void Fill(int* dest, int value, int size) + { + Fill((byte*)dest, value, size); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(uint[] dest, uint value) + { + fixed (uint* destPtr = dest) + { + Fill(destPtr, value, dest.Length * 4); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(int[] dest, int value) + { + fixed (int* destPtr = dest) + { + Fill(destPtr, value, dest.Length * 4); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(ushort* dest, ushort value, int size) + { + /* Broadcast 'value' to fill all the integer register (0x42 --> 0x42424242) */ + int valueFiller = value * 0x10001; + Fill((byte*)dest, valueFiller, size); + } + + unsafe public static void Fill(short* dest, short value, int size) + { + /* Broadcast 'value' to fill all the integer register (0x42 --> 0x42424242) */ + int valueFiller = (ushort)value * 0x10001; + Fill((byte*)dest, valueFiller, size); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(ushort[] dest, ushort value) + { + fixed (ushort* destPtr = dest) + { + Fill(destPtr, value, dest.Length * 2); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(short[] dest, short value) + { + fixed (short* destPtr = dest) + { + Fill(destPtr, value, dest.Length * 2); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(byte* dest, byte value, int size) + { + /* Broadcast 'value' fill all the integer register (0x42 --> 0x42424242) */ + int valueFiller = value * 0x1010101; + Fill(dest, valueFiller, size); + } + + unsafe public static void Fill(sbyte* dest, sbyte value, int size) + { + /* Broadcast 'value' fill all the integer register (0x42 --> 0x42424242) */ + int valueFiller = (byte)value * 0x1010101; + Fill((byte*)dest, valueFiller, size); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(byte[] dest, byte value) + { + fixed (byte* destPtr = dest) + { + Fill(destPtr, value, dest.Length); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + unsafe public static void Fill(sbyte[] dest, sbyte value) + { + fixed (sbyte* destPtr = dest) + { + Fill(destPtr, value, dest.Length); + } + } + } +} diff --git a/source/Cosmos.HAL/Drivers/Video/VBEDriver.cs b/source/Cosmos.HAL/Drivers/Video/VBEDriver.cs index 9dadebe3e..cc0a53df7 100644 --- a/source/Cosmos.HAL/Drivers/Video/VBEDriver.cs +++ b/source/Cosmos.HAL/Drivers/Video/VBEDriver.cs @@ -22,8 +22,8 @@ namespace Cosmos.HAL.Drivers VBEDisplayBankMode, VBEDisplayVirtualWidth, VBEDisplayVirtualHeight, - VBEDisPlayXOffset, - VBEDislyYOffset + VBEDisplayXOffset, + VBEDisplayYOffset }; [Flags] diff --git a/source/Cosmos.sln b/source/Cosmos.sln index fc6a046cc..1758e679b 100644 --- a/source/Cosmos.sln +++ b/source/Cosmos.sln @@ -295,6 +295,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphicTest", "..\Tests\Gra EndProject Project("{471EC4BB-E47E-4229-A789-D1F5F83B52D4}") = "GraphicTestBoot", "..\Tests\GraphicTest\GraphicTestBoot.Cosmos", "{9246BA1F-FBDB-4B09-806A-7968BF4D3EB9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cosmos Graphic Subsytem", "Cosmos Graphic Subsytem\Cosmos Graphic Subsytem.csproj", "{49F2C01D-D2C5-4564-810B-1AE92236C5C1}" +EndProject +Project("{471EC4BB-E47E-4229-A789-D1F5F83B52D4}") = "Cosmos Graphic SubsytemBoot", "Cosmos Graphic Subsytem\Cosmos Graphic SubsytemBoot.Cosmos", "{1BC71853-22F3-415D-A068-8E1FA8E8F05B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cosmos Graphic Subsystem", "Cosmos Graphic Subsystem", "{7634AC43-FE21-487F-B16A-25DE5B33E22E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1367,6 +1373,30 @@ Global {9246BA1F-FBDB-4B09-806A-7968BF4D3EB9}.Release|x64.Build.0 = Debug|x86 {9246BA1F-FBDB-4B09-806A-7968BF4D3EB9}.Release|x86.ActiveCfg = Debug|x86 {9246BA1F-FBDB-4B09-806A-7968BF4D3EB9}.Release|x86.Build.0 = Debug|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Debug|Any CPU.ActiveCfg = Debug|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Debug|Any CPU.Build.0 = Debug|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Debug|x64.ActiveCfg = Debug|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Debug|x64.Build.0 = Debug|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Debug|x86.ActiveCfg = Debug|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Debug|x86.Build.0 = Debug|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Release|Any CPU.ActiveCfg = Release|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Release|Any CPU.Build.0 = Release|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Release|x64.ActiveCfg = Release|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Release|x64.Build.0 = Release|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Release|x86.ActiveCfg = Release|x86 + {49F2C01D-D2C5-4564-810B-1AE92236C5C1}.Release|x86.Build.0 = Release|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Debug|Any CPU.ActiveCfg = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Debug|Any CPU.Build.0 = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Debug|x64.ActiveCfg = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Debug|x64.Build.0 = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Debug|x86.ActiveCfg = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Debug|x86.Build.0 = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Release|Any CPU.ActiveCfg = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Release|Any CPU.Build.0 = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Release|x64.ActiveCfg = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Release|x64.Build.0 = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Release|x86.ActiveCfg = Debug|x86 + {1BC71853-22F3-415D-A068-8E1FA8E8F05B}.Release|x86.Build.0 = Debug|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1483,5 +1513,8 @@ Global {156DAD1F-186F-4CFE-B769-573F44AB8439} = {2BE77488-5549-4957-8B23-A24828029093} {FB23BD72-AEC3-485E-B86C-8E7DB0B3BB9B} = {F104F6BC-EF8E-4408-A786-D570D7565231} {9246BA1F-FBDB-4B09-806A-7968BF4D3EB9} = {F104F6BC-EF8E-4408-A786-D570D7565231} + {49F2C01D-D2C5-4564-810B-1AE92236C5C1} = {7634AC43-FE21-487F-B16A-25DE5B33E22E} + {1BC71853-22F3-415D-A068-8E1FA8E8F05B} = {7634AC43-FE21-487F-B16A-25DE5B33E22E} + {7634AC43-FE21-487F-B16A-25DE5B33E22E} = {1698DD83-72A3-44CD-B088-4320A4014A95} EndGlobalSection EndGlobal diff --git a/source/XSharp.Compiler/XS.SSE.cs b/source/XSharp.Compiler/XS.SSE.cs index 933cedc13..1a06bbd5f 100644 --- a/source/XSharp.Compiler/XS.SSE.cs +++ b/source/XSharp.Compiler/XS.SSE.cs @@ -96,6 +96,26 @@ namespace XSharp.Compiler DoDestinationSource(destination, sourceLabel, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement); } + public static void MoveUPS(Register32 destination, RegisterXMM source, bool destinationIsIndirect = false, int? destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null) + { + DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement); + } + +#if false + public static void MoveUPS(Register32 destination, RegisterXMM source, bool destinationIsIndirect = false, Register32 destinationDisplacement = null, bool sourceIsIndirect = false, int? sourceDisplacement = null) + { + //DoDestinationSource(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement); + new MoveUPS() + { + DestinationReg = destination, + DestinationIsIndirect = destinationIsIndirect, + DestinationDisplacement = (int)destinationDisplacement, + SourceDisplacement = sourceDisplacement, + SourceReg = source + }; + } +#endif + public static void ConvertSS2SD(RegisterXMM destination, Register32 source, bool sourceIsIndirect = false) { new ConvertSS2SD() @@ -150,6 +170,16 @@ namespace XSharp.Compiler DestinationIsIndirect = isIndirect }; } + + public static void Shufps(RegisterXMM destination, RegisterXMM source, int bitmask) + { + new Shufps() + { + DestinationReg = destination, + SourceReg = source, + pseudoOpcode = (byte)bitmask + }; + } } } }