using System; using System.Collections.Generic; using Cosmos.Common; using System.Linq; using System.Text; using Cosmos.IL2CPU.Plugs; namespace Cosmos.Core { public class MemoryBlock { public readonly UInt32 Base; public readonly UInt32 Size; public readonly MemoryBlock08 Bytes; public readonly MemoryBlock16 Words; public readonly MemoryBlock32 DWords; public MemoryBlock(UInt32 aBase, UInt32 aSize) { Base = aBase; Size = aSize; Bytes = new MemoryBlock08(aBase, aSize); Words = new MemoryBlock16(aBase, aSize); DWords = new MemoryBlock32(aBase, aSize); } //TODO: Fill all these methods with fast ASM //TODO: Make an attribute that can be applied to methods to tell the copmiler to inline them to save // the overhead of a call on operations like this. // Need to check bounds for 16 and 32 better so offset cannot be size - 1 and then the 4 bytes write past the end public unsafe UInt32 this[UInt32 aByteOffset] { get { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } return *(UInt32*)(Base + aByteOffset); } set { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } (*(UInt32*)(Base + aByteOffset)) = value; } } public void Fill(UInt32 aData) { Fill(0, Size / 4, 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 UInt32* xDest = (UInt32*)(this.Base + aStart); for (UInt32 i = 0; i < aCount; i++) { *xDest = aData; xDest++; } } public void Fill(byte aData) { Fill(0, Size, aData); } public void Fill(UInt16 aData) { Fill(0, Size / 2, 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 UInt16* xDest = (UInt16*)(this.Base + aStart); for (UInt32 i = 0; i < aCount; i++) { *xDest = aData; xDest++; } } [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 byte* xDest = (byte*)(this.Base + aStart); for (UInt32 i = 0; i < aCount; i++) { *xDest = aData; xDest++; } } [DebugStub(Off = true)] public unsafe void MoveDown(UInt32 aDest, UInt32 aSrc, UInt32 aCount) { byte* xDest = (byte*)(this.Base + aDest); byte* xSrc = (byte*)(this.Base + aSrc); for (int i = 0; i < aCount; i++) { *xDest = *xSrc; xDest++; xSrc++; } } public void MoveUp(UInt32 aDest, UInt32 aSrc, UInt32 aCount) { throw new Exception("TODO"); } } public class MemoryBlock08 { public readonly UInt32 Base; public readonly UInt32 Size; internal MemoryBlock08(UInt32 aBase, UInt32 aSize) { Base = aBase; Size = aSize; } public unsafe byte this[UInt32 aByteOffset] { get { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } return *(byte*)(Base + aByteOffset); } set { if (aByteOffset >= Size) { // Also this exception gets eaten? throw new Exception("Memory access violation"); } (*(byte*)(Base + aByteOffset)) = value; } } } public class MemoryBlock16 { public readonly UInt32 Base; public readonly UInt32 Size; internal MemoryBlock16(UInt32 aBase, UInt32 aSize) { Base = aBase; Size = aSize; } public unsafe UInt16 this[UInt32 aByteOffset] { get { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } return *(UInt16*)(Base + aByteOffset); } set { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } (*(UInt16*)(Base + aByteOffset)) = value; } } } public class MemoryBlock32 { public readonly UInt32 Base; public readonly UInt32 Size; internal MemoryBlock32(UInt32 aBase, UInt32 aSize) { Base = aBase; Size = aSize; } public unsafe UInt32 this[UInt32 aByteOffset] { get { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } return *(UInt32*)(Base + aByteOffset); } set { if (aByteOffset >= Size) { throw new Exception("Memory access violation"); } (*(UInt32*)(Base + aByteOffset)) = value; } } } }