mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-31 13:21:05 +00:00
- Added Console.Clear() to Guess Demo (the boot text remained on screen) - Added to BCL test BitConverterTest (all failing), test for single / double arithmetic operations - Added to TestRunner BCLTest
135 lines
No EOL
8.4 KiB
C#
135 lines
No EOL
8.4 KiB
C#
using System;
|
|
using CPUx86 = Cosmos.Assembler.x86;
|
|
|
|
namespace Cosmos.IL2CPU.X86.IL
|
|
{
|
|
/// <summary>
|
|
/// Converts the value on top of the evaluation stack to float32.
|
|
/// </summary>
|
|
[Cosmos.IL2CPU.OpCode(ILOpCode.Code.Conv_R4)]
|
|
public class Conv_R4 : ILOp
|
|
{
|
|
public Conv_R4(Cosmos.Assembler.Assembler aAsmblr)
|
|
: base(aAsmblr)
|
|
{
|
|
}
|
|
|
|
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
|
|
{
|
|
var xSource = aOpCode.StackPopTypes[0];
|
|
var xSourceIsFloat = TypeIsFloat(xSource);
|
|
var xSourceSize = SizeOfType(xSource);
|
|
switch (xSourceSize)
|
|
{
|
|
case 1:
|
|
case 2:
|
|
{
|
|
new CPUx86.SSE.ConvertSI2SS { DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true };
|
|
new CPUx86.SSE.MoveSS { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.XMM0 };
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
if (!xSourceIsFloat)
|
|
{
|
|
if (IsIntegerSigned(xSource))
|
|
{
|
|
new CPUx86.SSE.ConvertSI2SS { DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true };
|
|
new CPUx86.SSE.MoveSS { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.XMM0 };
|
|
}
|
|
else
|
|
{
|
|
#if false
|
|
/*
|
|
* x86 assembler generated by GCC 4.86 with SSE2 arch enforced:
|
|
* uint2float:
|
|
*
|
|
* LCPI0_0:
|
|
* .quad 4841369599423283200 # double 4503599627370496
|
|
*
|
|
* push ebp
|
|
* mov ebp, esp
|
|
* sub esp, 8
|
|
* mov eax, dword ptr [ebp + 8]
|
|
* mov dword ptr [ebp - 4], eax
|
|
* movsd xmm0, qword ptr [.LCPI0_0]
|
|
* movaps xmm1, xmm0
|
|
* movd xmm2, eax
|
|
* por xmm2, xmm1
|
|
* subsd xmm2, xmm0
|
|
* cvtsd2ss xmm0, xmm2
|
|
* movss dword ptr [ebp - 8], xmm0
|
|
* ; Why moving the value on x87 registers after having avoided to touch them until now? Maybe is the x87 calling convention
|
|
* ; but we follow the .NET calling convention so we should push the result directly onto the stack
|
|
* fld dword ptr [ebp - 8]
|
|
* add esp, 8
|
|
* pop ebp
|
|
* ret
|
|
*
|
|
* Let's to write it in the Cosmos dialect...
|
|
*/
|
|
new CPUx86.Push { DestinationReg = CPUx86.Registers.EBP };
|
|
new CPUx86.Mov { DestinationReg = CPUx86.Registers.EBP, SourceReg = CPUx86.Registers.ESP };
|
|
new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceValue = 8 };
|
|
new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EBP + 8};
|
|
new CPUx86.Mov { DestinationReg = CPUx86.Registers.EBP - 4, SourceReg = CPUx86.Registers.EAX };
|
|
/* Magic number */
|
|
new CPUx86.SSE.MoveSD { DestinationReg = CPUx86.Registers.XMM0, SourceValue = 4841369599423283200 };
|
|
new CPUx86.SSE.MoveAPS { DestinationReg = CPUx86.Registers.XMM1, SourceReg = CPUx86.Registers.XMM0 };
|
|
new CPUx86.Mov { DestinationReg = CPUx86.Registers.XMM2, SourceReg = CPUx86.Registers.EAX };
|
|
new CPUx86.SSE.Por { DestinationReg = CPUx86.Registers.XMM2, SourceReg = CPUx86.Registers.XMM1 };
|
|
new CPUx86.SSE.SubSD { DestinationReg = CPUx86.Registers.XMM2, SourceReg = CPUx86.Registers.XMM0 };
|
|
new CPUx86.SSE.ConvertSD2SS { DestinationReg = CPUx86.Registers.XMM0, SourceReg = CPUx86.Registers.XMM2 };
|
|
new CPUx86.SSE.MoveSS { DestinationReg = CPUx86.Registers.EBP - 8, SourceReg = CPUx86.Registers.XMM0 };
|
|
//new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 8 };
|
|
//new CPUx86.x87.FloatLoad { DestinationReg = CPUx86.Registers.EBP - 8, Size = 32 };
|
|
// Let's try to avoid the x87 fld instruction in EPB - 8 there is the result already!
|
|
new CPUx86.Mov { DestinationReg = CPUx86.Registers.ESP, SourceReg = CPUx86.Registers.EBP - 8 };
|
|
//new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 8 };
|
|
new CPUx86.Pop { DestinationReg = CPUx86.Registers.EBP };
|
|
#endif
|
|
throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_R4.cs->Conversion of UInt32 to Float is not yet implemented!");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 8:
|
|
{
|
|
if (xSourceIsFloat)
|
|
{
|
|
new CPUx86.SSE.ConvertSD2SS { SourceReg = CPUx86.Registers.ESP, DestinationReg = CPUx86.Registers.XMM0, SourceIsIndirect = true };
|
|
new CPUx86.SSE.MoveSS { SourceReg = CPUx86.Registers.XMM0, DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true };
|
|
}
|
|
else
|
|
{
|
|
if (IsIntegerSigned(xSource))
|
|
{
|
|
/*
|
|
* Again there is no SSE instruction in x86 to do this conversion as we need a 64 Bit register to do this! So we are forced
|
|
* to use the legacy x87 FPU to do this operation. In x64 the SSE instruction ConvertSIQ2SS should exist.
|
|
*/
|
|
new CPUx86.x87.IntLoad { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true };
|
|
new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.Registers.ESP, Size = 32, DestinationIsIndirect = true };
|
|
|
|
//throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_R4.cs->Conversion of Int64 to Float is not yet implemented!");
|
|
}
|
|
else
|
|
{
|
|
throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_R4.cs->Conversion of UInt64 to Float is not yet implemented!");
|
|
}
|
|
}
|
|
|
|
// Why I need to do all this Pop / Pop / Pushing or I get stack corruption? The result in the stack as expected so?
|
|
new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX };
|
|
new CPUx86.Pop { DestinationReg = CPUx86.Registers.ECX };
|
|
new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
|
|
|
|
break;
|
|
}
|
|
default:
|
|
//EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_U4: SourceSize " + xStackItem.Size + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel );
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|
|
} |