diff --git a/source/Cosmos.IL2CPU/.editorconfig b/source/Cosmos.IL2CPU/.editorconfig index ad8cc0047..e2903681a 100644 --- a/source/Cosmos.IL2CPU/.editorconfig +++ b/source/Cosmos.IL2CPU/.editorconfig @@ -13,7 +13,7 @@ indent_size = 2 indent_size = 2 [IL/*.cs] -indent_size = 2 +indent_size = 4 [AppAssembler.cs] indent_size = 4 diff --git a/source/Cosmos.IL2CPU/IL/Ldelem_Ref.cs b/source/Cosmos.IL2CPU/IL/Ldelem_Ref.cs index 1c29b9567..c53730d08 100644 --- a/source/Cosmos.IL2CPU/IL/Ldelem_Ref.cs +++ b/source/Cosmos.IL2CPU/IL/Ldelem_Ref.cs @@ -1,61 +1,86 @@ -using System; using CPUx86 = Cosmos.Assembler.x86; using Cosmos.Assembler; using Cosmos.IL2CPU.IL.CustomImplementations.System; + namespace Cosmos.IL2CPU.X86.IL { - [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Ldelem_Ref )] - public class Ldelem_Ref : ILOp + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldelem_Ref)] + public class Ldelem_Ref: ILOp { - public Ldelem_Ref( Cosmos.Assembler.Assembler aAsmblr ) - : base( aAsmblr ) + public Ldelem_Ref(Cosmos.Assembler.Assembler aAsmblr) + : base(aAsmblr) { } - public static void Assemble(Cosmos.Assembler.Assembler aAssembler, uint aElementSize,bool isSigned , bool debugEnabled) + + public static void Assemble(Cosmos.Assembler.Assembler aAssembler, uint aElementSize, bool isSigned, bool debugEnabled) { - DoNullReferenceCheck(aAssembler, debugEnabled, 4); - if (aElementSize <= 0 || aElementSize > 8 || (aElementSize > 4 && aElementSize < 8)) - throw new Exception("Unsupported size for Ldelem_Ref: " + aElementSize); + DoNullReferenceCheck(aAssembler, debugEnabled, 4); + //if (aElementSize <= 0 || aElementSize > 8 || (aElementSize > 4 && aElementSize < 8)) + //{ + // throw new Exception("Unsupported size for Ldelem_Ref: " + aElementSize); + //} - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDX, SourceValue = aElementSize }; - new CPUx86.Multiply { DestinationReg = CPUx86.Registers.EDX }; + new CPUx86.Pop {DestinationReg = CPUx86.Registers.EAX}; + new CPUx86.Mov {DestinationReg = CPUx86.Registers.EDX, SourceValue = aElementSize}; + new CPUx86.Multiply {DestinationReg = CPUx86.Registers.EDX}; - //TODO: implement ObjectImpl first - new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = ( ObjectImpl.FieldDataOffset + 4 ) }; + new CPUx86.Add {DestinationReg = CPUx86.Registers.EAX, SourceValue = (ObjectImpl.FieldDataOffset + 4)}; - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDX }; - new CPUx86.Add { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EAX }; + if (aElementSize > 4) + { + // we start copying the last bytes + new CPUx86.Add {DestinationReg = CPUx86.Registers.EAX, SourceValue = aElementSize - 4}; + } - switch (aElementSize) - { - case 1: - if (isSigned) - new CPUx86.MoveSignExtend { DestinationReg = CPUx86.Registers.ECX, Size = 8, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true }; - else - new CPUx86.MoveZeroExtend { DestinationReg = CPUx86.Registers.ECX, Size = 8, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.ECX }; - break; - case 2: - if (isSigned) - new CPUx86.MoveSignExtend { DestinationReg = CPUx86.Registers.ECX, Size = 16, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true }; - else - new CPUx86.MoveZeroExtend { DestinationReg = CPUx86.Registers.ECX, Size = 16, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.ECX }; - break; - case 4: - new CPUx86.Push { DestinationReg = CPUx86.Registers.EDX, DestinationIsIndirect = true }; - break; - case 8: - new CPUx86.Push { DestinationReg = CPUx86.Registers.EDX, DestinationDisplacement = 4, DestinationIsIndirect = true }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.EDX, DestinationIsIndirect = true }; - break; - } + new CPUx86.Pop {DestinationReg = CPUx86.Registers.EDX}; + new CPUx86.Add {DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EAX}; + + var xSizeLeft = aElementSize; + while (xSizeLeft > 0) + { + var xCurrentStep = xSizeLeft % 4; + xSizeLeft = xSizeLeft / 4; + switch (xCurrentStep) + { + case 1: + if (isSigned) + { + new CPUx86.MoveSignExtend {DestinationReg = CPUx86.Registers.ECX, Size = 8, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true}; + } + else + { + new CPUx86.MoveZeroExtend {DestinationReg = CPUx86.Registers.ECX, Size = 8, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true}; + } + new CPUx86.Push {DestinationReg = CPUx86.Registers.ECX}; + break; + case 2: + if (isSigned) + { + new CPUx86.MoveSignExtend {DestinationReg = CPUx86.Registers.ECX, Size = 16, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true}; + } + else + { + new CPUx86.MoveZeroExtend {DestinationReg = CPUx86.Registers.ECX, Size = 16, SourceReg = CPUx86.Registers.EDX, SourceIsIndirect = true}; + } + new CPUx86.Push {DestinationReg = CPUx86.Registers.ECX}; + break; + case 0: + // copy a full dword + new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationIsIndirect = true}; + new CPUx86.Sub {DestinationReg = CPUx86.RegistersEnum.EDX, SourceValue = 4}; // move to previous 4 bytes + break; + //case 8: + // new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationDisplacement = 4, DestinationIsIndirect = true}; + // new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationIsIndirect = true}; + // break; + } + } } - public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) + public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { Assemble( Assembler, 4, false, DebugEnabled); + Assemble(Assembler, 4, false, DebugEnabled); } } -} \ No newline at end of file +}