Merge pull request #705 from CosmosOS/issue-694

List Fixes
This commit is contained in:
jp2masa 2017-10-23 14:38:50 +01:00 committed by GitHub
commit cfcf19cc53
4 changed files with 189 additions and 39 deletions

View file

@ -2,33 +2,71 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Cosmos.TestRunner;
namespace Cosmos.Compiler.Tests.Bcl.System.Collections.Generic
{
public static class ListTest
{
public static void Execute()
{
var xList = new List<int>();
Assert.AreEqual(0, xList.Count, "Count != 0 at start!");
xList.Add(0);
xList.Add(1);
xList.Add(2);
Assert.AreEqual(3, xList.Count, "After adding 3 items, count != 3");
Assert.AreEqual(0, xList[0], "List[0] != 0");
Assert.AreEqual(1, xList[1], "List[1] != 1");
Assert.AreEqual(2, xList[2], "List[2] != 2");
Assert.AreEqual(0, xList[0], "List<int>.Add: xList[0] != 0");
Assert.AreEqual(1, xList[1], "List<int>.Add: xList[1] != 1");
Assert.AreEqual(2, xList[2], "List<int>.Add: xList[2] != 2");
var xArray = xList.ToArray();
Assert.AreEqual(3, xArray.Length, "xArray.Length != 3");
Assert.AreEqual(0, xArray[0], "xArray[0] != 0");
Assert.AreEqual(1, xArray[1], "xArray[1] != 1");
Assert.AreEqual(2, xArray[2], "xArray[2] != 2");
Assert.AreEqual(3, xArray.Length, "List<int>.ToArray: xArray.Length != 3");
Assert.AreEqual(0, xArray[0], "List<int>.ToArray: xArray[0] != 0");
Assert.AreEqual(1, xArray[1], "List<int>.ToArray: xArray[1] != 1");
Assert.AreEqual(2, xArray[2], "List<int>.ToArray: xArray[2] != 2");
xList.Insert(1, 5);
Assert.AreEqual(0, xList[0], "List<int>.Insert: xList[0] != 0");
Assert.AreEqual(5, xList[1], "List<int>.Insert: xList[1] != 5");
Assert.AreEqual(1, xList[2], "List<int>.Insert: xList[2] != 1");
Assert.AreEqual(2, xList[3], "List<int>.Insert: xList[3] != 2");
xList.RemoveAt(2);
Assert.AreEqual(0, xList[0], "List<int>.RemoveAt: xList[0] != 0");
Assert.AreEqual(5, xList[1], "List<int>.RemoveAt: xList[1] != 5");
Assert.AreEqual(2, xList[2], "List<int>.RemoveAt: xList[2] != 2");
// Commented tests depend on #583
//xList.AddRange(new List<int>() { 3, 4, 5 });
//Assert.AreEqual(0, xList[0], "List<int>.AddRange: xList[0] != 0");
//Assert.AreEqual(5, xList[1], "List<int>.AddRange: xList[1] != 5");
//Assert.AreEqual(2, xList[2], "List<int>.AddRange: xList[2] != 2");
//Assert.AreEqual(3, xList[2], "List<int>.AddRange: xList[3] != 3");
//Assert.AreEqual(4, xList[2], "List<int>.AddRange: xList[4] != 4");
//Assert.AreEqual(5, xList[2], "List<int>.AddRange: xList[5] != 5");
//xList.RemoveRange(2, 2);
//Assert.AreEqual(0, xList[0], "List<int>.RemoveRange: xList[0] != 0");
//Assert.AreEqual(5, xList[1], "List<int>.RemoveRange: xList[1] != 5");
//Assert.AreEqual(4, xList[2], "List<int>.RemoveRange: xList[2] != 4");
//Assert.AreEqual(5, xList[2], "List<int>.RemoveRange: xList[3] != 5");
//var xRange = xList.GetRange(1, 3);
//Assert.AreEqual(5, xRange[0], "List<int>.GetRange: xRange[0] != 5");
//Assert.AreEqual(4, xRange[1], "List<int>.GetRange: xRange[1] != 4");
//Assert.AreEqual(5, xRange[2], "List<int>.GetRange: xRange[2] != 5");
}
}
}
}

View file

@ -1,14 +1,15 @@
using XSharp.Assembler;
using Cosmos.IL2CPU.API;
using XSharp;
using CPUx86 = XSharp.Assembler.x86;
using XSharp.Assembler;
using XSharp.Assembler.x86;
using static XSharp.XSRegisters;
namespace Cosmos.Core_Asm
{
public class ArrayInternalCopyAsm : AssemblerMethod
{
private const int SourceArrayDisplacement = 36;
private const int SourceIndexDisplacement = 32;
private const int SourceIndexDisplacement = 28;
private const int DestinationArrayDisplacement = 24;
private const int DestinationIndexDisplacement = 16;
private const int LengthDisplacement = 12;
@ -24,40 +25,152 @@ namespace Cosmos.Core_Asm
public override void AssembleNew(Assembler aAssembler, object aMethodInfo)
{
var xArrayCopyReverseLabel = "ArrayCopy_Reverse";
var xArrayCopyReverseLoopLabel = "ArrayCopy_Reverse_Loop";
var xArrayCopyEndLabel = "ArrayCopy_End";
XS.Comment("Source");
XS.Comment("Element size");
XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: SourceArrayDisplacement);
XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset);
XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // element size
XS.Set(EAX, EBP, sourceDisplacement: SourceArrayDisplacement);
XS.Add(EAX, ObjectUtils.FieldDataOffset);
XS.Set(EAX, EAX, sourceIsIndirect: true); // element size
XS.Comment("Source ptr");
XS.Set(XSRegisters.EBX, XSRegisters.EBP, sourceDisplacement: SourceIndexDisplacement);
XS.Multiply(XSRegisters.EBX);
XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset + 4); // first element
XS.Set(XSRegisters.ESI, XSRegisters.EBP, sourceDisplacement: SourceArrayDisplacement);
XS.Add(XSRegisters.ESI, XSRegisters.EAX); // source ptr
XS.Set(EBX, EBP, sourceDisplacement: SourceIndexDisplacement);
XS.Multiply(EBX);
XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // first element
XS.Set(ESI, EBP, sourceDisplacement: SourceArrayDisplacement);
XS.Add(ESI, EAX); // source ptr
XS.Comment("Destination");
XS.Comment("Element size");
XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: DestinationArrayDisplacement);
XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset);
XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // element size
XS.Set(EAX, EBP, sourceDisplacement: DestinationArrayDisplacement);
XS.Add(EAX, ObjectUtils.FieldDataOffset);
XS.Set(EAX, EAX, sourceIsIndirect: true); // element size
XS.Comment("Destination ptr");
XS.Set(XSRegisters.ECX, XSRegisters.EBP, sourceDisplacement: DestinationIndexDisplacement);
XS.Multiply(XSRegisters.ECX);
XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset + 4); // first element
XS.Set(XSRegisters.EDI, XSRegisters.EBP, sourceDisplacement: DestinationArrayDisplacement);
XS.Add(XSRegisters.EDI, XSRegisters.EAX); // destination ptr
XS.Set(ECX, EBP, sourceDisplacement: DestinationIndexDisplacement);
XS.Multiply(ECX);
XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // first element
XS.Set(EDI, EBP, sourceDisplacement: DestinationArrayDisplacement);
XS.Add(EDI, EAX); // destination ptr
XS.Compare(EDI, ESI);
XS.Jump(ConditionalTestEnum.Equal, xArrayCopyEndLabel);
XS.Comment("Copy byte count");
XS.Comment("Element size");
XS.Set(XSRegisters.EAX, XSRegisters.EBP, sourceDisplacement: DestinationArrayDisplacement);
XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset);
XS.Set(XSRegisters.EAX, XSRegisters.EAX, sourceIsIndirect: true); // element size
XS.Set(EAX, EBP, sourceDisplacement: DestinationArrayDisplacement);
XS.Add(EAX, ObjectUtils.FieldDataOffset);
XS.Set(EAX, EAX, sourceIsIndirect: true); // element size
XS.Comment("Count");
XS.Set(XSRegisters.EDX, XSRegisters.EBP, sourceDisplacement: LengthDisplacement);
XS.Multiply(XSRegisters.EDX);
XS.Set(XSRegisters.ECX, XSRegisters.EAX);
new CPUx86.Movs { Size = 8, Prefixes = CPUx86.InstructionPrefixes.Repeat };
XS.Set(EDX, EBP, sourceDisplacement: LengthDisplacement);
// if length is 0, jump to end
XS.Compare(EDX, 0);
XS.Jump(ConditionalTestEnum.Equal, xArrayCopyEndLabel);
XS.Multiply(EDX);
XS.Set(ECX, EAX);
// if source and destination are equal, jump to end
XS.Set(EAX, ESI);
XS.Add(EAX, ECX);
XS.Compare(EDI, EAX);
XS.Jump(ConditionalTestEnum.Equal, xArrayCopyEndLabel);
XS.Jump(ConditionalTestEnum.LessThanOrEqualTo, xArrayCopyReverseLabel);
new Movs { Size = 8, Prefixes = InstructionPrefixes.Repeat };
XS.Jump(xArrayCopyEndLabel);
// source ptr + size >= destination ptr
XS.Label(xArrayCopyReverseLabel);
XS.Comment("Array Reverse Copy: source ptr + size >= destination ptr");
XS.Add(ESI, ECX);
XS.Add(EDI, ECX);
XS.Label(xArrayCopyReverseLoopLabel);
XS.Decrement(ESI);
XS.Decrement(EDI);
XS.Decrement(ECX);
XS.Set(AL, ESI, sourceIsIndirect: true);
XS.Set(EDI, AL, destinationIsIndirect: true);
XS.Compare(ECX, 0);
XS.Jump(ConditionalTestEnum.NotEqual, xArrayCopyReverseLoopLabel);
XS.Label(xArrayCopyEndLabel);
}
}
}
// Old implementation
// (it's a good memcpy implementation, as it doesn't check for array overlapping, so it can't be used for Array.Copy)
//using Cosmos.Assembler;
//using Cosmos.Assembler.x86;
//using Cosmos.IL2CPU.API;
//using XSharp.Common;
//using static XSharp.Common.XSRegisters;
//namespace Cosmos.Core_Asm
//{
// public class ArrayInternalCopyAsm : AssemblerMethod
// {
// private const int SourceArrayDisplacement = 36;
// private const int SourceIndexDisplacement = 28;
// private const int DestinationArrayDisplacement = 24;
// private const int DestinationIndexDisplacement = 16;
// private const int LengthDisplacement = 12;
// /* void Copy(
// * Array sourceArray, ebp + 36
// * int sourceIndex, ebp + 28
// * Array destinationArray, ebp + 24
// * int destinationIndex, ebp + 16
// * int length, ebp + 12
// * bool reliable); ebp + 8
// */
// public override void AssembleNew(Assembler.Assembler aAssembler, object aMethodInfo)
// {
// XS.Comment("Source");
// XS.Comment("Element size");
// XS.Set(EAX, EBP, sourceDisplacement: SourceArrayDisplacement);
// XS.Add(EAX, ObjectUtils.FieldDataOffset);
// XS.Set(EAX, EAX, sourceIsIndirect: true); // element size
// XS.Comment("Source ptr");
// XS.Set(EBX, EBP, sourceDisplacement: SourceIndexDisplacement);
// XS.Multiply(EBX);
// XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // first element
// XS.Set(ESI, EBP, sourceDisplacement: SourceArrayDisplacement);
// XS.Add(ESI, EAX); // source ptr
// XS.Comment("Destination");
// XS.Comment("Element size");
// XS.Set(EAX, EBP, sourceDisplacement: DestinationArrayDisplacement);
// XS.Add(EAX, ObjectUtils.FieldDataOffset);
// XS.Set(EAX, EAX, sourceIsIndirect: true); // element size
// XS.Comment("Destination ptr");
// XS.Set(ECX, EBP, sourceDisplacement: DestinationIndexDisplacement);
// XS.Multiply(ECX);
// XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // first element
// XS.Set(EDI, EBP, sourceDisplacement: DestinationArrayDisplacement);
// XS.Add(EDI, EAX); // destination ptr
// XS.Comment("Copy byte count");
// XS.Comment("Element size");
// XS.Set(EAX, EBP, sourceDisplacement: DestinationArrayDisplacement);
// XS.Add(EAX, ObjectUtils.FieldDataOffset);
// XS.Set(EAX, EAX, sourceIsIndirect: true); // element size
// XS.Comment("Count");
// XS.Set(EDX, EBP, sourceDisplacement: LengthDisplacement);
// XS.Multiply(EDX);
// XS.Set(ECX, EAX);
// new Movs { Size = 8, Prefixes = InstructionPrefixes.Repeat };
// }
// }
//}

View file

@ -14,9 +14,9 @@ namespace Cosmos.Core_Asm
private const int CountDisplacement = 8;
/*public static void BlockCopy(
* Array src, [ebp + 24]
* int srcOffset, [ebp + 20]
* Array dst, [ebp + 16]
* Array src, [ebp + 32]
* int srcOffset, [ebp + 24]
* Array dst, [ebp + 20]
* int dstOffset, [ebp + 12]
* int count); [ebp + 8]
*/

View file

@ -8,7 +8,6 @@ using static XSharp.XSRegisters;
namespace Cosmos.Core_Asm
{
//TODO: This asm refs Hardware.. should not.. its a higher ring
public class CPUUpdateIDTAsm : AssemblerMethod
{
private static MethodBase GetMethodDef(Assembly aAssembly, string aType, string aMethodName, bool aErrorWhenNotFound)