Cosmos/source/Cosmos.Core.Plugs/MemoryOperations/MemoryOperationsFillFastAsm.cs
fanoI db5b713090 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
2017-03-05 20:32:55 +01:00

62 lines
2.3 KiB
C#

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