mirror of
https://github.com/danbulant/Cosmos
synced 2026-06-06 08:12:14 +00:00
commit
552ded82b8
30 changed files with 547 additions and 565 deletions
|
|
@ -17,11 +17,12 @@
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
|
@ -85,6 +86,7 @@
|
||||||
<Compile Include="System\BooleanTest.cs" />
|
<Compile Include="System\BooleanTest.cs" />
|
||||||
<Compile Include="System\ByteTest.cs" />
|
<Compile Include="System\ByteTest.cs" />
|
||||||
<Compile Include="System\CharTest.cs" />
|
<Compile Include="System\CharTest.cs" />
|
||||||
|
<Compile Include="System\Collections\Generic\DictionaryTest.cs" />
|
||||||
<Compile Include="System\Collections\Generic\ListTest.cs" />
|
<Compile Include="System\Collections\Generic\ListTest.cs" />
|
||||||
<Compile Include="System\Collections\Generic\QueueTest.cs" />
|
<Compile Include="System\Collections\Generic\QueueTest.cs" />
|
||||||
<Compile Include="System\DecimalTest.cs" />
|
<Compile Include="System\DecimalTest.cs" />
|
||||||
|
|
@ -100,6 +102,7 @@
|
||||||
<Compile Include="System\UInt16Test.cs" />
|
<Compile Include="System\UInt16Test.cs" />
|
||||||
<Compile Include="System\UInt32Test.cs" />
|
<Compile Include="System\UInt32Test.cs" />
|
||||||
<Compile Include="System\UInt64Test.cs" />
|
<Compile Include="System\UInt64Test.cs" />
|
||||||
|
<Compile Include="System\UnsafeCodeTest.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Cosmos.TestRunner.TestController\Cosmos.TestRunner.TestController.csproj">
|
<ProjectReference Include="..\Cosmos.TestRunner.TestController\Cosmos.TestRunner.TestController.csproj">
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,11 @@ namespace Cosmos.Compiler.Tests.Bcl
|
||||||
BooleanTest.Execute();
|
BooleanTest.Execute();
|
||||||
SingleTest.Execute();
|
SingleTest.Execute();
|
||||||
DoubleTest.Execute();
|
DoubleTest.Execute();
|
||||||
|
|
||||||
#if false
|
|
||||||
BitConverterTest.Execute();
|
BitConverterTest.Execute();
|
||||||
|
UnsafeCodeTest.Execute();
|
||||||
|
|
||||||
|
#if false
|
||||||
DecimalTest.Execute();
|
DecimalTest.Execute();
|
||||||
//BitConverterTest.Execute();
|
|
||||||
//DecimalTest.Execute();
|
|
||||||
System.Collections.Generic.ListTest.Execute();
|
System.Collections.Generic.ListTest.Execute();
|
||||||
System.Collections.Generic.QueueTest.Execute();
|
System.Collections.Generic.QueueTest.Execute();
|
||||||
System.DelegatesTest.Execute();
|
System.DelegatesTest.Execute();
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
|
|
||||||
Assert.IsTrue((result == expectedResult), "BitConverter.ToString(intBytes) doesn't work: result " + result + " != " + expectedResult);
|
Assert.IsTrue((result == expectedResult), "BitConverter.ToString(intBytes) doesn't work: result " + result + " != " + expectedResult);
|
||||||
|
|
||||||
|
|
||||||
long aLong = 1;
|
long aLong = 1;
|
||||||
|
|
||||||
byte[] longBytes = BitConverter.GetBytes(aLong);
|
byte[] longBytes = BitConverter.GetBytes(aLong);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
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 DictionaryTest
|
||||||
|
{
|
||||||
|
public static void Execute()
|
||||||
|
{
|
||||||
|
Dictionary<String, Object> commands = new Dictionary<String, Object>()
|
||||||
|
{
|
||||||
|
{"echo", "ECHO"},
|
||||||
|
{"reboot", "REBOOT" },
|
||||||
|
{"shutdown", "SHUTDOWN"}
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.IsTrue(commands.ContainsKey("echo"), "Dictionary ContainsKey does not work");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,13 +10,14 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
// This does not compile:
|
// This does not compile:
|
||||||
public static void Execute()
|
public static void Execute()
|
||||||
{
|
{
|
||||||
#if false
|
|
||||||
Decimal value;
|
Decimal value;
|
||||||
String result;
|
String result;
|
||||||
String expectedResult;
|
String expectedResult;
|
||||||
|
|
||||||
value = 42.42M; // It exists Single.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
|
value = 42.42M; // It exists Single.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
|
||||||
|
|
||||||
|
#if false
|
||||||
// This does not compile: Error: Exception: System.Exception: Native code encountered, plug required. Please see https://github.com/CosmosOS/Cosmos/wiki/Plugs). System.String System.Number.FormatDecimal(System.Decimal, System.String, System.Globalization.NumberFormatInfo
|
// This does not compile: Error: Exception: System.Exception: Native code encountered, plug required. Please see https://github.com/CosmosOS/Cosmos/wiki/Plugs). System.String System.Number.FormatDecimal(System.Decimal, System.String, System.Globalization.NumberFormatInfo
|
||||||
result = value.ToString();
|
result = value.ToString();
|
||||||
expectedResult = "42.42";
|
expectedResult = "42.42";
|
||||||
|
|
|
||||||
|
|
@ -26,31 +26,63 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
String result;
|
String result;
|
||||||
String expectedResult;
|
String expectedResult;
|
||||||
|
|
||||||
value = 42.42; // It exists Single.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
|
/* First start with some weird value (not really numbers) that the IEEE standard has */
|
||||||
|
value = Double.PositiveInfinity;
|
||||||
// It seems to be a problem in BitConverter.GetBytes with a Double value that in turn broke toString() for now a solution to this is not found
|
|
||||||
#if false
|
|
||||||
value = 1;
|
|
||||||
|
|
||||||
// Let's try to see as a ByteArray
|
|
||||||
byte[] doubleBytes = BitConverter.GetBytes(value);
|
|
||||||
|
|
||||||
Console.WriteLine($"doubleByte is of {doubleBytes.Length} bytes");
|
|
||||||
|
|
||||||
foreach (byte aByte in doubleBytes)
|
|
||||||
Console.WriteLine(aByte);
|
|
||||||
|
|
||||||
//Console.WriteLine("Double (as long) " + DoubleToUlong(value));
|
|
||||||
|
|
||||||
result = value.ToString();
|
result = value.ToString();
|
||||||
expectedResult = "1";
|
expectedResult = "∞";
|
||||||
|
|
||||||
// The test fails the conversion returns "Double Underrange"
|
Assert.IsTrue((result == expectedResult), "Double.ToString of INF doesn't work");
|
||||||
Assert.IsTrue((result == expectedResult), "Double.ToString doesn't work");
|
|
||||||
|
value = Double.NegativeInfinity;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "-∞";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Double.ToString of -INF doesn't work");
|
||||||
|
|
||||||
|
value = Double.NaN;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "NaN";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Double.ToString of -NaN doesn't work");
|
||||||
|
|
||||||
|
/* Another special value is '0' */
|
||||||
|
value = 0;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "0";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Double.ToString of 0 doesn't work");
|
||||||
|
|
||||||
|
/* A negative value */
|
||||||
|
value = -42.42;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "-42.42";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Double.ToString of negative number doesn't work");
|
||||||
|
|
||||||
|
/* A big value (to be correct toString should convert it in scientific notation) */
|
||||||
|
value = 9223372036854775808;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "9223372036854775808";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Double.ToString of big number doesn't work");
|
||||||
|
|
||||||
|
/* OK now a normal value */
|
||||||
|
value = 42.42; // It exists Double.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "42.42";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Double.ToString of normal number doesn't work");
|
||||||
|
|
||||||
// Now let's try to concat to a String using '+' operator
|
// Now let's try to concat to a String using '+' operator
|
||||||
result = "The value of the Double is " + value;
|
result = "The value of the Double is " + value;
|
||||||
expectedResult = "The value of the Double is 1";
|
expectedResult = "The value of the Double is 42.42";
|
||||||
|
|
||||||
Assert.IsTrue((result == expectedResult), "String concat (Double) doesn't work");
|
Assert.IsTrue((result == expectedResult), "String concat (Double) doesn't work");
|
||||||
|
|
||||||
|
|
@ -59,14 +91,14 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
// Actually 'expectedResult' should be the same so...
|
// Actually 'expectedResult' should be the same so...
|
||||||
Assert.IsTrue((result == expectedResult), "String format (Double) doesn't work");
|
Assert.IsTrue((result == expectedResult), "String format (Double) doesn't work");
|
||||||
|
|
||||||
|
#if false
|
||||||
// Now let's Get the HashCode of a value
|
// Now let's Get the HashCode of a value
|
||||||
int resultAsInt = value.GetHashCode();
|
int resultAsInt = value.GetHashCode();
|
||||||
|
|
||||||
// actually the Hash Code of a Int32 is the same value
|
// actually the Hash Code of a Int32 is the same value
|
||||||
Assert.IsTrue((resultAsInt == value), "Double.GetHashCode() doesn't work");
|
Assert.IsTrue((resultAsInt == value), "Double.GetHashCode() doesn't work");
|
||||||
#endif
|
|
||||||
|
|
||||||
#if false
|
|
||||||
// Now let's try ToString() again but printed in hex (this test fails for now!)
|
// Now let's try ToString() again but printed in hex (this test fails for now!)
|
||||||
result = value.ToString("X2");
|
result = value.ToString("X2");
|
||||||
expectedResult = "0x7FFFFFFF";
|
expectedResult = "0x7FFFFFFF";
|
||||||
|
|
@ -163,22 +195,9 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
Assert.IsTrue((DoublesAreEqual(valueNegated, 42d)), "(double) negation doesn't work");
|
Assert.IsTrue((DoublesAreEqual(valueNegated, 42d)), "(double) negation doesn't work");
|
||||||
|
|
||||||
// Let's try if it works in the other way too
|
// Let's try if it works in the other way too
|
||||||
//value = 42.0;
|
value = 42.0;
|
||||||
//valueNegated = -value;
|
valueNegated = -value;
|
||||||
//Assert.IsTrue((DoublesAreEqual(valueNegated, -42.0f)), "(double) negation of positive float doesn't work");
|
Assert.IsTrue((DoublesAreEqual(valueNegated, -42.0f)), "(double) negation of positive double doesn't work");
|
||||||
#if false
|
|
||||||
unchecked
|
|
||||||
{
|
|
||||||
ulong anULong = (ulong)-1;
|
|
||||||
byte[] anULongAsBytes = BitConverter.GetBytes(anULong);
|
|
||||||
value = (double)anULong;
|
|
||||||
byte[] valueAsBytes = BitConverter.GetBytes(value);
|
|
||||||
|
|
||||||
//Assert.IsTrue((DoublesAreEqual(value, 18446744073709551615d)), "(double) from ulong operator doesn't work");
|
|
||||||
|
|
||||||
Assert.IsTrue((DoublesAreEqual(value, 18446744073709551615d)), "(double) from ulong operator doesn't work long is " + BitConverter.ToString(anULongAsBytes) + " value (as bytes) is " + BitConverter.ToString(valueAsBytes));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,24 +18,24 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
result = value.ToString();
|
result = value.ToString();
|
||||||
expectedResult = "2147483647";
|
expectedResult = "2147483647";
|
||||||
|
|
||||||
//Assert.IsTrue((result == expectedResult), "Int32.ToString doesn't work");
|
Assert.IsTrue((result == expectedResult), "Int32.ToString doesn't work");
|
||||||
|
|
||||||
// Now let's try to concat to a String using '+' operator
|
// Now let's try to concat to a String using '+' operator
|
||||||
result = "The Maximum value of an Int32 is " + value;
|
result = "The Maximum value of an Int32 is " + value;
|
||||||
expectedResult = "The Maximum value of an Int32 is 2147483647";
|
expectedResult = "The Maximum value of an Int32 is 2147483647";
|
||||||
|
|
||||||
//Assert.IsTrue((result == expectedResult), "String concat (Int32) doesn't work");
|
Assert.IsTrue((result == expectedResult), "String concat (Int32) doesn't work");
|
||||||
|
|
||||||
// Now let's try to use '$ instead of '+'
|
// Now let's try to use '$ instead of '+'
|
||||||
result = $"The Maximum value of an Int32 is {value}";
|
result = $"The Maximum value of an Int32 is {value}";
|
||||||
// Actually 'expectedResult' should be the same so...
|
// Actually 'expectedResult' should be the same so...
|
||||||
//Assert.IsTrue((result == expectedResult), "String format (Int32) doesn't work");
|
Assert.IsTrue((result == expectedResult), "String format (Int32) doesn't work");
|
||||||
|
|
||||||
// Now let's Get the HashCode of a value
|
// Now let's Get the HashCode of a value
|
||||||
int resultAsInt = value.GetHashCode();
|
int resultAsInt = value.GetHashCode();
|
||||||
|
|
||||||
// actually the Hash Code of an Int32 is the same value
|
// actually the Hash Code of an Int32 is the same value
|
||||||
//Assert.IsTrue((resultAsInt == value), "Int32.GetHashCode() doesn't work");
|
Assert.IsTrue((resultAsInt == value), "Int32.GetHashCode() doesn't work");
|
||||||
|
|
||||||
#if false
|
#if false
|
||||||
// Now let's try ToString() again but printed in hex (this test fails for now!)
|
// Now let's try ToString() again but printed in hex (this test fails for now!)
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,24 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
val2 = long.Parse("42");
|
val2 = long.Parse("42");
|
||||||
Assert.IsTrue(val2 == 42, "Parsing Int64 doesn't work.");
|
Assert.IsTrue(val2 == 42, "Parsing Int64 doesn't work.");
|
||||||
|
|
||||||
|
/* Let's test right shift */
|
||||||
|
value = 4631166901565532406;
|
||||||
|
|
||||||
|
val2 = value >> 20;
|
||||||
|
Assert.IsTrue(val2 == 4416624929013, "long right shift does not work");
|
||||||
|
|
||||||
|
val2 = value >> 52;
|
||||||
|
Assert.IsTrue(val2 == 1028, "long right shift (count >=32) does not work");
|
||||||
|
|
||||||
|
/* ... and now left shift */
|
||||||
|
value = 4631166901565532406;
|
||||||
|
|
||||||
|
val2 = value << 20;
|
||||||
|
Assert.IsTrue(val2 == 6640827866535690240, "long left shift does not work got " + val2);
|
||||||
|
|
||||||
|
val2 = value << 52;
|
||||||
|
Assert.IsTrue(val2 == -8115486528521633792, "long left shift (count >=32) does not work got " + val2);
|
||||||
|
|
||||||
#if false
|
#if false
|
||||||
|
|
||||||
// Now let's try ToString() again but printed in hex (this test fails for now!)
|
// Now let's try ToString() again but printed in hex (this test fails for now!)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
private static bool SinglesAreEqual(Single left, Single right)
|
private static bool SinglesAreEqual(Single left, Single right)
|
||||||
{
|
{
|
||||||
// Define the tolerance for variation in their values
|
// Define the tolerance for variation in their values
|
||||||
Single difference = (Single)Math.Abs(left * .00001);
|
Single difference = (Single) Math.Abs(left * .00001);
|
||||||
|
|
||||||
if (Math.Abs(left - right) <= difference)
|
if (Math.Abs(left - right) <= difference)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -19,38 +19,65 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The double== equality operator is so imprecise to not be really ever useful we should be happy if the two values are "similar" */
|
|
||||||
private static bool DoublesAreEqual(double left, double right)
|
|
||||||
{
|
|
||||||
// Define the tolerance for variation in their values
|
|
||||||
double difference = Math.Abs(left * .00001);
|
|
||||||
|
|
||||||
if (Math.Abs(left - right) <= difference)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void negPositive()
|
|
||||||
{
|
|
||||||
// Let's try if it works in the other way too
|
|
||||||
//float value = 42.0f;
|
|
||||||
//float valueNegated = -value;
|
|
||||||
//Assert.IsTrue((SinglesAreEqual(valueNegated, -42.0f)), "(float) negation of positive float doesn't work got " + valueNegated);
|
|
||||||
|
|
||||||
}
|
|
||||||
public static void Execute()
|
public static void Execute()
|
||||||
{
|
{
|
||||||
Single value;
|
Single value;
|
||||||
String result;
|
String result;
|
||||||
String expectedResult;
|
String expectedResult;
|
||||||
|
|
||||||
value = 42.42F; // It exists Single.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
|
/* First start with some weird value (not really numbers) that the IEEE standard has */
|
||||||
|
value = Single.PositiveInfinity;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "∞";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Single.ToString of INF doesn't work");
|
||||||
|
|
||||||
|
value = Single.NegativeInfinity;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "-∞";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Single.ToString of -INF doesn't work");
|
||||||
|
|
||||||
|
value = Single.NaN;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "NaN";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Single.ToString of -NaN doesn't work");
|
||||||
|
|
||||||
|
/* Another special value is '0' */
|
||||||
|
value = 0f;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "0";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Single.ToString of 0 doesn't work");
|
||||||
|
|
||||||
|
/* A negative value */
|
||||||
|
value = -42.42f;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "-42.42";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Single.ToString of negative number doesn't work");
|
||||||
|
|
||||||
|
/* A big value (to be correct toString should convert it in scientific notation) */
|
||||||
|
value = 9223372036854775808f;
|
||||||
|
|
||||||
|
result = value.ToString();
|
||||||
|
expectedResult = "9223372036854775808";
|
||||||
|
|
||||||
|
Assert.IsTrue((result == expectedResult), "Single.ToString of big number doesn't work");
|
||||||
|
|
||||||
|
/* OK now a normal value */
|
||||||
|
value = 42.42F; // It exists Single.MaxValue but it is a too big value an can be represented only on Scientific notation but then how to confront with a String?
|
||||||
|
|
||||||
result = value.ToString();
|
result = value.ToString();
|
||||||
expectedResult = "42.42";
|
expectedResult = "42.42";
|
||||||
|
|
||||||
Assert.IsTrue((result == expectedResult), "Single.ToString doesn't work");
|
Assert.IsTrue((result == expectedResult), "Single.ToString of normal number doesn't work");
|
||||||
|
|
||||||
// Now let's try to concat to a String using '+' operator
|
// Now let's try to concat to a String using '+' operator
|
||||||
result = "The value of the Single is " + value;
|
result = "The value of the Single is " + value;
|
||||||
|
|
@ -101,42 +128,35 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
Single otherValue = 2.20f;
|
Single otherValue = 2.20f;
|
||||||
|
|
||||||
OperationResult = value + otherValue;
|
OperationResult = value + otherValue;
|
||||||
//expectedResult = "44.62";
|
|
||||||
|
|
||||||
Assert.IsTrue((SinglesAreEqual(OperationResult, 44.62f)), "float operator+ doesn't work");
|
Assert.IsTrue((SinglesAreEqual(OperationResult, 44.62f)), "float operator+ doesn't work");
|
||||||
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator+ doesn't work");
|
|
||||||
|
|
||||||
// Now test subtraction
|
// Now test subtraction
|
||||||
OperationResult = value - otherValue;
|
OperationResult = value - otherValue;
|
||||||
//expectedResult = "40.22";
|
//expectedResult = "40.22";
|
||||||
|
|
||||||
Assert.IsTrue((SinglesAreEqual(OperationResult, 40.22f)), "float operator- doesn't work");
|
Assert.IsTrue((SinglesAreEqual(OperationResult, 40.22f)), "float operator- doesn't work");
|
||||||
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator- doesn't work");
|
|
||||||
|
|
||||||
// Now test multiplication
|
// Now test multiplication
|
||||||
otherValue = 2.00f; // I'll change 'otherValue' to 2.00f because if not the result is too much wrong to make sense...
|
otherValue = 2.00f; // I'll change 'otherValue' to 2.00f because if not the result is too much wrong to make sense...
|
||||||
OperationResult = value * otherValue;
|
OperationResult = value * otherValue;
|
||||||
//expectedResult = "84.84";
|
|
||||||
|
|
||||||
Assert.IsTrue((SinglesAreEqual(OperationResult, 84.84f)), "float operator* doesn't work");
|
Assert.IsTrue((SinglesAreEqual(OperationResult, 84.84f)), "float operator* doesn't work");
|
||||||
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator* doesn't work");
|
|
||||||
|
|
||||||
// Now test division
|
// Now test division
|
||||||
OperationResult = value / otherValue;
|
OperationResult = value / otherValue;
|
||||||
//expectedResult = "21.21";
|
|
||||||
|
|
||||||
Assert.IsTrue((SinglesAreEqual(OperationResult, 21.21f)), "float operator/ doesn't work");
|
Assert.IsTrue((SinglesAreEqual(OperationResult, 21.21f)), "float operator/ doesn't work");
|
||||||
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator/ doesn't work");
|
|
||||||
|
|
||||||
// Now test division again but with dividend 0 the expected result should be Double.PositiveInfinity
|
// Now test division again but with dividend 0 the expected result should be Double.PositiveInfinity
|
||||||
OperationResult = value / 0.00f;
|
OperationResult = value / 0.00f;
|
||||||
|
|
||||||
Assert.IsTrue((OperationResult == Single.PositiveInfinity), "single operator/0 doesn't work");
|
Assert.IsTrue((OperationResult == Single.PositiveInfinity), "flot operator/0 doesn't work");
|
||||||
|
|
||||||
// Now test division again but with all values as 0 the expected result should be Double.NaN
|
// Now test division again but with all values as 0 the expected result should be Double.NaN
|
||||||
OperationResult = 0.00f / 0.00f;
|
OperationResult = 0.00f / 0.00f;
|
||||||
|
|
||||||
Assert.IsTrue((Single.IsNaN(OperationResult)), "single operator/(0/0) doesn't work");
|
Assert.IsTrue((Single.IsNaN(OperationResult)), "float operator/(0/0) doesn't work");
|
||||||
|
|
||||||
// Now test some castings operations
|
// Now test some castings operations
|
||||||
byte valueAsByte = (byte)value;
|
byte valueAsByte = (byte)value;
|
||||||
|
|
@ -178,31 +198,14 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
value = (float)anULong;
|
value = (float)anULong;
|
||||||
Assert.IsTrue((SinglesAreEqual(value, 9223372036854775849f)), "(float) from ulong operator doesn't work");
|
Assert.IsTrue((SinglesAreEqual(value, 9223372036854775849f)), "(float) from ulong operator doesn't work");
|
||||||
|
|
||||||
//value = -42.0f;
|
value = -42.0f;
|
||||||
//float valueNegated = -value;
|
float valueNegated = -value;
|
||||||
//Assert.IsTrue((SinglesAreEqual(valueNegated, 42.0f)), "(float) negation doesn't work");
|
Assert.IsTrue((SinglesAreEqual(valueNegated, 42.0f)), "(float) negation doesn't work");
|
||||||
|
|
||||||
//negPositive();
|
|
||||||
|
|
||||||
#if false
|
|
||||||
// Let's try if it works in the other way too
|
// Let's try if it works in the other way too
|
||||||
value = 42.0f;
|
value = 42.0f;
|
||||||
valueNegated = -value;
|
valueNegated = -value;
|
||||||
Assert.IsTrue((SinglesAreEqual(valueNegated, -42.0f)), "(float) negation of positive float doesn't work");
|
Assert.IsTrue((SinglesAreEqual(valueNegated, -42.0f)), "(float) negation of positive float doesn't work");
|
||||||
#endif
|
|
||||||
|
|
||||||
#if false
|
|
||||||
//ulong anULong = 9223372036854775849;
|
|
||||||
ulong anULong = 9423372036854775870;
|
|
||||||
value = (float)anULong;
|
|
||||||
#if true
|
|
||||||
byte[] valueAsBytes = BitConverter.GetBytes(value);
|
|
||||||
|
|
||||||
Assert.IsTrue((SinglesAreEqual(value, 9223372036854775849f)), "(float) from ulong operator doesn't work returns " + value + " as bytes " + BitConverter.ToString(valueAsBytes));
|
|
||||||
#else
|
|
||||||
Assert.IsTrue((SinglesAreEqual(value, 9423372036854775870f)), "(float) from ulong operator doesn't work: ");
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
Assert.IsTrue(("a" + "b") == "ab", "concatting 2 string using + doesn't work");
|
Assert.IsTrue(("a" + "b") == "ab", "concatting 2 string using + doesn't work");
|
||||||
Assert.IsTrue(("a" + 'b') == "ab", "concatting 1 string and 1 character doesn't work");
|
Assert.IsTrue(("a" + 'b') == "ab", "concatting 1 string and 1 character doesn't work");
|
||||||
|
|
||||||
|
string a = "a";
|
||||||
|
string b = "b";
|
||||||
|
string result = a + b;
|
||||||
|
Assert.IsTrue(result == "ab", "concatting 2 string (not optimizable) using + doesn't work"); // Fails
|
||||||
|
|
||||||
char x = 'a';
|
char x = 'a';
|
||||||
string y = "a";
|
string y = "a";
|
||||||
Assert.IsTrue(x.ToString() == y, "String == operator ");
|
Assert.IsTrue(x.ToString() == y, "String == operator ");
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,22 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
|
|
||||||
Assert.IsTrue((value == 18446744073709551615), "Negative Double to UInt64 conversion doesn't work");
|
Assert.IsTrue((value == 18446744073709551615), "Negative Double to UInt64 conversion doesn't work");
|
||||||
|
|
||||||
|
value = 4631166901565532406u;
|
||||||
|
|
||||||
|
val2 = value >> 20;
|
||||||
|
Assert.IsTrue(val2 == 4416624929013, "ulong right shift does not work");
|
||||||
|
|
||||||
|
val2 = value >> 52;
|
||||||
|
Assert.IsTrue(val2 == 1028, "ulong right shift (count >=32) does not work");
|
||||||
|
|
||||||
|
/* ... and now left shift */
|
||||||
|
value = 4631166901565532406;
|
||||||
|
|
||||||
|
val2 = value << 20;
|
||||||
|
Assert.IsTrue(val2 == 6640827866535690240, "ulong left shift does not work");
|
||||||
|
|
||||||
|
val2 = value << 52;
|
||||||
|
Assert.IsTrue(val2 == 10331257545187917824, "ulong left shift (count >=32) does not work");
|
||||||
|
|
||||||
#if false
|
#if false
|
||||||
// Now let's try ToString() again but printed in hex (this test fails for now!)
|
// Now let's try ToString() again but printed in hex (this test fails for now!)
|
||||||
|
|
|
||||||
57
Tests/Cosmos.Compiler.Tests.Bcl/System/UnsafeCodeTest.cs
Normal file
57
Tests/Cosmos.Compiler.Tests.Bcl/System/UnsafeCodeTest.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Cosmos.Compiler.Tests.Bcl.System
|
||||||
|
{
|
||||||
|
using Cosmos.TestRunner;
|
||||||
|
|
||||||
|
unsafe class UnsafeCodeTest
|
||||||
|
{
|
||||||
|
static long DoubleToInt64Bits(double value)
|
||||||
|
{
|
||||||
|
return *(long*)(&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ulong Test(ref ulong a)
|
||||||
|
{
|
||||||
|
a = 12345678;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Execute()
|
||||||
|
{
|
||||||
|
|
||||||
|
long val = Int64.MaxValue;
|
||||||
|
long* p = &val;
|
||||||
|
long newVal = *p;
|
||||||
|
Assert.IsTrue(val == newVal, $"Pointer deferencing failed expected {val} got {newVal}");
|
||||||
|
|
||||||
|
/* This the same thing BitConverter does to convert a Double to a Long it should fail in this case too */
|
||||||
|
double d = 1.0;
|
||||||
|
long asLong = *(long*)(&d);
|
||||||
|
|
||||||
|
byte[] hexDump;
|
||||||
|
hexDump = BitConverter.GetBytes(asLong);
|
||||||
|
|
||||||
|
Assert.IsTrue(asLong == 0x3FF0000000000000, "double asLong is wrong!");
|
||||||
|
|
||||||
|
ulong aLong = 0;
|
||||||
|
ulong retVal;
|
||||||
|
retVal = Test(ref aLong);
|
||||||
|
|
||||||
|
Assert.IsTrue(retVal == 12345678, "Ulong ref passing not works");
|
||||||
|
|
||||||
|
asLong = DoubleToInt64Bits(d);
|
||||||
|
hexDump = BitConverter.GetBytes(asLong);
|
||||||
|
|
||||||
|
Console.WriteLine("asLong is : " + BitConverter.ToString(hexDump, 0));
|
||||||
|
Assert.IsTrue(asLong == 0x3FF0000000000000, "DoubleToInt64Bits is wrong!");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Cosmos.Common
|
namespace Cosmos.Common
|
||||||
{
|
{
|
||||||
|
|
@ -131,6 +127,254 @@ namespace Cosmos.Common
|
||||||
return xResult;
|
return xResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This implementation could only print values which integer part is < ULONG_MAX, the only solution would have been to use BigInteger but then
|
||||||
|
* I'd have an analogous problem: to plug BigInteger.ToString() and I don't know how many other things.
|
||||||
|
* We will retain this code for now it is OK for debug purposes and big value should be printed in scientific notation to be readable anyway...
|
||||||
|
*/
|
||||||
|
public static string GetNumberString(float aValue)
|
||||||
|
{
|
||||||
|
var singleBytes = BitConverter.GetBytes(aValue);
|
||||||
|
int hexVal = BitConverter.ToInt32(singleBytes, 0);
|
||||||
|
|
||||||
|
/* Let's extract the parts that compose our single: sign, exponent and mantissa */
|
||||||
|
bool isNeg = (hexVal >> 31) != 0;
|
||||||
|
int exp = ((hexVal >> 23) & 0xFF);
|
||||||
|
ulong mantissa = (ulong)(hexVal & 0x7FFFFF);
|
||||||
|
|
||||||
|
ulong intPart = 0, fracPart = 0;
|
||||||
|
|
||||||
|
/* First we handle the special cases INF, NaN, 0 and denormalized float */
|
||||||
|
switch (exp)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* INF or NaN?
|
||||||
|
*/
|
||||||
|
case 0xFF:
|
||||||
|
if (mantissa == 0)
|
||||||
|
{
|
||||||
|
if (isNeg)
|
||||||
|
return "-∞";
|
||||||
|
else
|
||||||
|
return "∞";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* It could exist -NaN but this is always printed as NaN */
|
||||||
|
return "NaN";
|
||||||
|
|
||||||
|
/* 0 or denormalized float? */
|
||||||
|
case 0x00:
|
||||||
|
if (mantissa == 0)
|
||||||
|
return "0";
|
||||||
|
/* Denormalized float have always exp -126 */
|
||||||
|
else
|
||||||
|
exp = -126;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Normalized float the exponent is unbiased and the implicit leading one is placed in the mantissa */
|
||||||
|
default:
|
||||||
|
exp -= 127;
|
||||||
|
mantissa |= 0x800000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp >= 23)
|
||||||
|
{
|
||||||
|
intPart = mantissa << (exp - 23);
|
||||||
|
}
|
||||||
|
else if (exp >= 0)
|
||||||
|
{
|
||||||
|
intPart = mantissa >> (23 - exp);
|
||||||
|
fracPart = (mantissa << (exp + 1)) & 0xFFFFFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fracPart = (mantissa & 0xFFFFFF) >> (-(exp + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
string result = "";
|
||||||
|
|
||||||
|
if (isNeg)
|
||||||
|
{
|
||||||
|
result += "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
result += intPart.ToString();
|
||||||
|
int usedDigits = intPart.ToString().Length;
|
||||||
|
if (fracPart == 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result += ".";
|
||||||
|
|
||||||
|
if (usedDigits >= 7)
|
||||||
|
{
|
||||||
|
usedDigits = 6;
|
||||||
|
}
|
||||||
|
for (int m = usedDigits; m < 7; m++)
|
||||||
|
{
|
||||||
|
fracPart = (fracPart << 3) + (fracPart << 1);
|
||||||
|
|
||||||
|
char p = (char)((fracPart >> 24) + '0');
|
||||||
|
result += p;
|
||||||
|
|
||||||
|
fracPart &= 0xFFFFFF;
|
||||||
|
}
|
||||||
|
fracPart = (fracPart << 3) + (fracPart << 1);
|
||||||
|
char remain = (char)((fracPart >> 24) + '0');
|
||||||
|
if ((remain > '5') && (result[result.Length - 1] > '0'))
|
||||||
|
{
|
||||||
|
char[] answer = result.ToCharArray();
|
||||||
|
int digitPos = answer.Length - 1;
|
||||||
|
char digit = result[digitPos];
|
||||||
|
answer[digitPos] = (char)(digit + 1);
|
||||||
|
while (answer[digitPos] > '9')
|
||||||
|
{
|
||||||
|
answer[digitPos] = '0';
|
||||||
|
digitPos--;
|
||||||
|
digit = result[digitPos];
|
||||||
|
if (digit == '.')
|
||||||
|
{
|
||||||
|
digitPos--;
|
||||||
|
digit = result[digitPos];
|
||||||
|
}
|
||||||
|
answer[digitPos] = (char)(digit + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = new string(answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result[result.Length - 1] == '0')
|
||||||
|
{
|
||||||
|
result = result.Substring(0, result.Length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This implementation could only print values which integer part is < ULONG_MAX, the only solution would have been to use BigInteger but then
|
||||||
|
* I'd have an analogous problem: to plug BigInteger.ToString() and I don't know how many other things.
|
||||||
|
* We will retain this code for now it is OK for debug purposes and big value should be printed in scientific notation to be readable anyway...
|
||||||
|
*/
|
||||||
|
public static string GetNumberString(double aValue)
|
||||||
|
{
|
||||||
|
long hexVal = BitConverter.DoubleToInt64Bits(aValue);
|
||||||
|
|
||||||
|
/* Let's extract the parts that compose our double: sign, exponent and mantissa */
|
||||||
|
bool isNeg = (hexVal >> 63) != 0;
|
||||||
|
int exp = (int)((hexVal >> 52) & 0x07FF);
|
||||||
|
ulong mantissa = (ulong)(hexVal & 0x0FFFFFFFFFFFFF);
|
||||||
|
|
||||||
|
ulong intPart = 0, fracPart = 0;
|
||||||
|
|
||||||
|
/* First we handle the special cases INF, NaN, 0 and denormalized float */
|
||||||
|
switch (exp)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* INF or NaN?
|
||||||
|
*/
|
||||||
|
case 0x07ff:
|
||||||
|
if (mantissa == 0)
|
||||||
|
{
|
||||||
|
if (isNeg)
|
||||||
|
return "-∞";
|
||||||
|
else
|
||||||
|
return "∞";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* It could exist -NaN but this is always printed as NaN */
|
||||||
|
return "NaN";
|
||||||
|
|
||||||
|
/* 0 or denormalized double? */
|
||||||
|
case 0x0000:
|
||||||
|
if (mantissa == 0)
|
||||||
|
return "0";
|
||||||
|
/* Denormalized float have always exp -1022 */
|
||||||
|
else
|
||||||
|
exp = -1022;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Normalized double the exponent is unbiased and the implicit leading one is placed in the mantissa */
|
||||||
|
default:
|
||||||
|
exp -= 1023;
|
||||||
|
mantissa |= 0x10000000000000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp >= 52)
|
||||||
|
{
|
||||||
|
intPart = mantissa << (exp - 52);
|
||||||
|
}
|
||||||
|
else if (exp >= 0)
|
||||||
|
{
|
||||||
|
intPart = mantissa >> (52 - exp);
|
||||||
|
fracPart = (mantissa << (exp + 1)) & 0x1FFFFFFFFFFFFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fracPart = (mantissa & 0x1FFFFFFFFFFFFF) >> (-(exp + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
string result = "";
|
||||||
|
|
||||||
|
if (isNeg)
|
||||||
|
{
|
||||||
|
result += "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
result += intPart.ToString();
|
||||||
|
int usedDigits = result.Length;
|
||||||
|
if (fracPart == 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result += ".";
|
||||||
|
|
||||||
|
if (usedDigits >= 15)
|
||||||
|
{
|
||||||
|
usedDigits = 14;
|
||||||
|
}
|
||||||
|
for (int m = usedDigits; m < 15; m++)
|
||||||
|
{
|
||||||
|
fracPart = (fracPart << 3) + (fracPart << 1);
|
||||||
|
char p = (char)(((fracPart >> 53) & 0xFF) + '0');
|
||||||
|
result += p;
|
||||||
|
|
||||||
|
fracPart &= 0x1FFFFFFFFFFFFF;
|
||||||
|
}
|
||||||
|
fracPart = (fracPart << 3) + (fracPart << 1);
|
||||||
|
char remain = (char)((fracPart >> 53) + '0');
|
||||||
|
if ((remain > '5') && (result[result.Length - 1] > '0'))
|
||||||
|
{
|
||||||
|
char[] answer = result.ToCharArray();
|
||||||
|
int digitPos = answer.Length - 1;
|
||||||
|
char digit = result[digitPos];
|
||||||
|
answer[digitPos] = (char)(digit + 1);
|
||||||
|
while (answer[digitPos] > '9')
|
||||||
|
{
|
||||||
|
answer[digitPos] = '0';
|
||||||
|
digitPos--;
|
||||||
|
digit = result[digitPos];
|
||||||
|
if (digit == '.')
|
||||||
|
{
|
||||||
|
digitPos--;
|
||||||
|
digit = result[digitPos];
|
||||||
|
}
|
||||||
|
answer[digitPos] = (char)(digit + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = new string(answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result[result.Length - 1] == '0')
|
||||||
|
{
|
||||||
|
result = result.Substring(0, result.Length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static int GetStringToNumber(string aString)
|
public static int GetStringToNumber(string aString)
|
||||||
{
|
{
|
||||||
bool xIsNegative = false;
|
bool xIsNegative = false;
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ namespace Cosmos.IL2CPU
|
||||||
DataMembers.Add(new DataMember(@"__uint2double_const", new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x41 }));
|
DataMembers.Add(new DataMember(@"__uint2double_const", new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x41 }));
|
||||||
DataMembers.Add(new DataMember(@"__ulong2double_const", 0x5F800000));
|
DataMembers.Add(new DataMember(@"__ulong2double_const", 0x5F800000));
|
||||||
DataMembers.Add(new DataMember(@"__doublesignbit", 0x8000000000000000));
|
DataMembers.Add(new DataMember(@"__doublesignbit", 0x8000000000000000));
|
||||||
//DataMembers.Add(new DataMember(@"__floatsignbit", 0x80000000));
|
DataMembers.Add(new DataMember(@"__floatsignbit", 0x80000000));
|
||||||
|
|
||||||
if (mComPort > 0)
|
if (mComPort > 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
||||||
XS.SSE2.AddSD(XMM1, XMM0);
|
XS.SSE2.AddSD(XMM1, XMM0);
|
||||||
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
|
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
|
||||||
|
|
||||||
#if false
|
|
||||||
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
|
|
||||||
XS.Add(ESP, 8);
|
|
||||||
new CPUx86.x87.FloatAdd { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, Size = 64 };
|
|
||||||
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else // long
|
else // long
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -75,26 +75,6 @@ namespace Cosmos.IL2CPU.X86.IL {
|
||||||
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
||||||
XS.Add(ESP, 4);
|
XS.Add(ESP, 4);
|
||||||
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
||||||
// This is the x87 version I left it here commented if in future will be needed...
|
|
||||||
#if false
|
|
||||||
XS.Set(XSRegisters.ESI, 1);
|
|
||||||
// esi = 1
|
|
||||||
XS.Xor(XSRegisters.EDI, XSRegisters.EDI);
|
|
||||||
// edi = 0
|
|
||||||
|
|
||||||
// value 1
|
|
||||||
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
|
|
||||||
// value 2
|
|
||||||
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
|
|
||||||
XS.FPU.FloatCompareAndSet(ST1);
|
|
||||||
// if zero is set, ST(0) == ST(i)
|
|
||||||
new ConditionalMove { Condition = ConditionalTestEnum.Equal, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
|
|
||||||
// pops fpu stack
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.Add(XSRegisters.ESP, 16);
|
|
||||||
XS.Push(XSRegisters.EDI);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -56,20 +56,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
||||||
XS.Add(ESP, 4);
|
XS.Add(ESP, 4);
|
||||||
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
||||||
// This is the x87 version I left it here commented if in future will be needed...
|
|
||||||
#if false
|
|
||||||
// value 1
|
|
||||||
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
|
|
||||||
// value 2
|
|
||||||
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
|
|
||||||
XS.FPU.FloatCompareAndSet(ST1);
|
|
||||||
// if carry is set, ST(0) < ST(i)
|
|
||||||
new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
|
|
||||||
// pops fpu stack
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.Add(XSRegisters.ESP, 16);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -54,20 +54,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
||||||
XS.Add(ESP, 4);
|
XS.Add(ESP, 4);
|
||||||
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
||||||
// This is the x87 version I left it here commented if in future will be needed...
|
|
||||||
#if false
|
|
||||||
// value 1
|
|
||||||
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
|
|
||||||
// value 2
|
|
||||||
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
|
|
||||||
XS.FPU.FloatCompareAndSet(ST1);
|
|
||||||
// if carry is set, ST(0) < ST(i)
|
|
||||||
new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
|
|
||||||
// pops fpu stack
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.Add(XSRegisters.ESP, 16);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -60,20 +60,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
||||||
XS.Add(ESP, 4);
|
XS.Add(ESP, 4);
|
||||||
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
||||||
// This is the x87 version I left it here commented if in future will be needed...
|
|
||||||
#if false
|
|
||||||
// value 2
|
|
||||||
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
|
|
||||||
// value 1
|
|
||||||
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
|
|
||||||
XS.FPU.FloatCompareAndSet(ST1);
|
|
||||||
// if carry is set, ST(0) < ST(i)
|
|
||||||
new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
|
|
||||||
// pops fpu stack
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.Add(XSRegisters.ESP, 16);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -53,20 +53,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
// We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack!
|
||||||
XS.Add(ESP, 4);
|
XS.Add(ESP, 4);
|
||||||
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
XS.Set(ESP, EBX, destinationIsIndirect: true);
|
||||||
// This is the x87 version I left it here commented if in future will be needed...
|
|
||||||
#if false
|
|
||||||
// value 2
|
|
||||||
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
|
|
||||||
// value 1
|
|
||||||
new FloatLoad { DestinationReg = RegistersEnum.ESP, Size = 64, DestinationDisplacement = 8, DestinationIsIndirect = true };
|
|
||||||
XS.FPU.FloatCompareAndSet(ST1);
|
|
||||||
// if carry is set, ST(0) < ST(i)
|
|
||||||
new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI };
|
|
||||||
// pops fpu stack
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.FPU.FloatStoreAndPop(ST0);
|
|
||||||
XS.Add(XSRegisters.ESP, 16);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,18 +35,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
||||||
XS.SSE2.DivSD(XMM1, XMM0);
|
XS.SSE2.DivSD(XMM1, XMM0);
|
||||||
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
|
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
|
||||||
// x87 version left here for future use
|
|
||||||
#if false
|
|
||||||
// TODO add 0/0 infinity/infinity X/infinity
|
|
||||||
// value 1
|
|
||||||
new CPUx86.x87.FloatLoad { DestinationReg = CPUx86.RegistersEnum.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8 };
|
|
||||||
// value 2
|
|
||||||
new CPUx86.x87.FloatDivide { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, Size = 64 };
|
|
||||||
// override value 1
|
|
||||||
new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.RegistersEnum.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8 };
|
|
||||||
// pop value 2
|
|
||||||
XS.Add(XSRegisters.ESP, 8);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,131 +17,49 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode )
|
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
|
||||||
{
|
{
|
||||||
var xOpVar = (OpVar)aOpCode;
|
var xOpVar = (OpVar)aOpCode;
|
||||||
|
|
||||||
var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, xOpVar.Value);
|
var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, xOpVar.Value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function GetArgumentDisplacement() does not give the correct displacement for the Ldarga opcode
|
||||||
|
* we need to "fix" it subtracting the argSize and 4
|
||||||
|
*/
|
||||||
|
Type xArgType;
|
||||||
|
if (aMethod.MethodBase.IsStatic)
|
||||||
|
{
|
||||||
|
xArgType = aMethod.MethodBase.GetParameters()[xOpVar.Value].ParameterType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (xOpVar.Value == 0u)
|
||||||
|
{
|
||||||
|
xArgType = aMethod.MethodBase.DeclaringType;
|
||||||
|
if (xArgType.IsValueType)
|
||||||
|
{
|
||||||
|
xArgType = xArgType.MakeByRefType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xArgType = aMethod.MethodBase.GetParameters()[xOpVar.Value - 1].ParameterType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint xArgRealSize = SizeOfType(xArgType);
|
||||||
|
uint xArgSize = Align(xArgRealSize, 4);
|
||||||
|
XS.Comment("Arg type = " + xArgType.ToString());
|
||||||
|
XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize);
|
||||||
|
|
||||||
|
xDisplacement -= (int)(xArgSize - 4);
|
||||||
|
XS.Comment("Real displacement " + xDisplacement);
|
||||||
|
|
||||||
XS.Set(XSRegisters.EBX, (uint)(xDisplacement));
|
XS.Set(XSRegisters.EBX, (uint)(xDisplacement));
|
||||||
XS.Set(XSRegisters.EAX, XSRegisters.EBP);
|
XS.Set(XSRegisters.EAX, XSRegisters.EBP);
|
||||||
XS.Add(XSRegisters.EAX, XSRegisters.EBX);
|
XS.Add(XSRegisters.EAX, XSRegisters.EBX);
|
||||||
XS.Push(XSRegisters.EAX);
|
XS.Push(XSRegisters.EAX);
|
||||||
|
|
||||||
// if (aMethod.MethodBase.DeclaringType.FullName == "Cosmos.Kernel.Plugs.Console"
|
|
||||||
// && aMethod.MethodBase.Name == "Write"
|
|
||||||
// && aMethod.MethodBase.GetParameters()[0].ParameterType == typeof(int))
|
|
||||||
// {
|
|
||||||
// Console.Write("");
|
|
||||||
// }
|
|
||||||
// Cosmos.IL2CPU.ILOpCodes.OpVar xOpVar = ( Cosmos.IL2CPU.ILOpCodes.OpVar )aOpCode;
|
|
||||||
// var xMethodInfo = aMethod.MethodBase as System.Reflection.MethodInfo;
|
|
||||||
// uint xReturnSize = 0;
|
|
||||||
// if( xMethodInfo != null )
|
|
||||||
// {
|
|
||||||
// xReturnSize = Align( SizeOfType( xMethodInfo.ReturnType ), 4 );
|
|
||||||
// }
|
|
||||||
// uint xOffset = 8;
|
|
||||||
// var xCorrectedOpValValue = xOpVar.Value;
|
|
||||||
// if( !aMethod.MethodBase.IsStatic && xOpVar.Value > 0 )
|
|
||||||
// {
|
|
||||||
// // if the method has a $this, the OpCode value includes the this at index 0, but GetParameters() doesnt include the this
|
|
||||||
// xCorrectedOpValValue -= 1;
|
|
||||||
// }
|
|
||||||
// var xParams = aMethod.MethodBase.GetParameters();
|
|
||||||
// for( int i = xParams.Length - 1; i > xCorrectedOpValValue; i-- )
|
|
||||||
// {
|
|
||||||
// var xSize = Align( SizeOfType( xParams[ i ].ParameterType ), 4 );
|
|
||||||
// xOffset += xSize;
|
|
||||||
// }
|
|
||||||
// var xCurArgSize = Align( SizeOfType( xParams[ xCorrectedOpValValue ].ParameterType ), 4 );
|
|
||||||
// uint xArgSize = 0;
|
|
||||||
// foreach( var xParam in xParams )
|
|
||||||
// {
|
|
||||||
// xArgSize += Align( SizeOfType( xParam.ParameterType ), 4 );
|
|
||||||
// }
|
|
||||||
// xReturnSize = 0;
|
|
||||||
// uint xExtraSize = 0;
|
|
||||||
// if( xReturnSize > xArgSize )
|
|
||||||
// {
|
|
||||||
// xExtraSize = xArgSize - xReturnSize;
|
|
||||||
// }
|
|
||||||
// xOffset += xExtraSize;
|
|
||||||
//#warning TODO: check this
|
|
||||||
// XS.Push(XSRegisters.EBP);
|
|
||||||
|
|
||||||
// for( int i = 0; i < ( xCurArgSize / 4 ); i++ )
|
|
||||||
// {
|
|
||||||
// XS.Push(( uint )( xCurArgSize - ( ( i + 1 ) * 4 ) ));
|
|
||||||
// }
|
|
||||||
// Assembler.Stack.Push( ( int )xCurArgSize, xParams[ xCorrectedOpValValue ].ParameterType );
|
|
||||||
|
|
||||||
// //for( int i = 0; i < ( mSize / 4 ); i++ )
|
|
||||||
// //{
|
|
||||||
// // mVirtualAddresses[ i ] = ( mOffset + ( ( i + 1 ) * 4 ) + 4 );
|
|
||||||
// //}
|
|
||||||
// //mAddress = aMethodInfo.Arguments[ aIndex ].VirtualAddresses.First();
|
|
||||||
|
|
||||||
|
|
||||||
// Assembler.Stack.Push( new StackContents.Item( 4, typeof( uint ) ) );
|
|
||||||
|
|
||||||
// //XS.Push(( uint )mAddress);
|
|
||||||
// //
|
|
||||||
// Assembler.Stack.Push( new StackContents.Item( 4, typeof( uint ) ) );
|
|
||||||
|
|
||||||
// new Add( Assembler ).Execute( aMethod, aOpCode );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// using System;
|
|
||||||
// using System.Linq;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// using CPU = Cosmos.Assembler.x86;
|
|
||||||
// using Cosmos.IL2CPU.X86;
|
|
||||||
//
|
|
||||||
// namespace Cosmos.IL2CPU.IL.X86 {
|
|
||||||
// [Cosmos.Assembler.OpCode(OpCodeEnum.Ldarga)]
|
|
||||||
// public class Ldarga: Op {
|
|
||||||
// private int mAddress;
|
|
||||||
// private string mNextLabel;
|
|
||||||
// private string mCurLabel;
|
|
||||||
// private uint mCurOffset;
|
|
||||||
// private MethodInformation mMethodInformation;
|
|
||||||
// protected void SetArgIndex(int aIndex, MethodInformation aMethodInfo) {
|
|
||||||
// mAddress = aMethodInfo.Arguments[aIndex].VirtualAddresses.First();
|
|
||||||
// }
|
|
||||||
// public Ldarga(MethodInformation aMethodInfo, int aIndex, string aCurrentLabel, uint aCurrentOffset, string aNextLabel)
|
|
||||||
// : base(null, aMethodInfo) {
|
|
||||||
// SetArgIndex(aIndex, aMethodInfo);
|
|
||||||
//
|
|
||||||
// mMethodInformation = aMethodInfo;
|
|
||||||
// mCurOffset = aCurrentOffset;
|
|
||||||
// mCurLabel = aCurrentLabel;
|
|
||||||
// mNextLabel = aNextLabel;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public Ldarga(ILReader aReader, MethodInformation aMethodInfo)
|
|
||||||
// : base(aReader, aMethodInfo) {
|
|
||||||
// if (aReader != null) {
|
|
||||||
// SetArgIndex(aReader.OperandValueInt32, aMethodInfo);
|
|
||||||
// //ParameterDefinition xParam = aReader.Operand as ParameterDefinition;
|
|
||||||
// //if (xParam != null) {
|
|
||||||
// // SetArgIndex(xParam.Sequence - 1, aMethodInfo);
|
|
||||||
// //}
|
|
||||||
// }
|
|
||||||
// mMethodInformation = aMethodInfo;
|
|
||||||
// mCurOffset = aReader.Position;
|
|
||||||
// mCurLabel = IL.Op.GetInstructionLabel(aReader);
|
|
||||||
// mNextLabel = IL.Op.GetInstructionLabel(aReader.NextPosition);
|
|
||||||
// }
|
|
||||||
// public override void DoAssemble() {
|
|
||||||
// XS.Push(XSRegisters.EBP);
|
|
||||||
// Assembler.Stack.Push(new StackContent(4, typeof(uint)));
|
|
||||||
// XS.Push((uint)mAddress);
|
|
||||||
// Assembler.Stack.Push(new StackContent(4, typeof(uint)));
|
|
||||||
// Add(Assembler, GetServiceProvider(), mCurLabel, mMethodInformation, mCurOffset, mNextLabel);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,18 +35,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
||||||
XS.SSE2.MulSD(XMM1, XMM0);
|
XS.SSE2.MulSD(XMM1, XMM0);
|
||||||
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
|
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
|
||||||
// x87 code left for future use
|
|
||||||
#if false
|
|
||||||
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
|
|
||||||
XS.Add(ESP, 8);
|
|
||||||
new CPUx86.x87.FloatMul
|
|
||||||
{
|
|
||||||
DestinationReg = CPUx86.RegistersEnum.ESP,
|
|
||||||
DestinationIsIndirect = true,
|
|
||||||
Size = 64
|
|
||||||
};
|
|
||||||
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
[Cosmos.IL2CPU.OpCode( ILOpCode.Code.Neg )]
|
[Cosmos.IL2CPU.OpCode( ILOpCode.Code.Neg )]
|
||||||
public class Neg : ILOp
|
public class Neg : ILOp
|
||||||
{
|
{
|
||||||
static bool varDone = false;
|
|
||||||
|
|
||||||
public Neg( Cosmos.Assembler.Assembler aAsmblr )
|
public Neg( Cosmos.Assembler.Assembler aAsmblr )
|
||||||
: base( aAsmblr )
|
: base( aAsmblr )
|
||||||
{
|
{
|
||||||
|
|
@ -29,12 +27,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
|
XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
|
||||||
XS.SSE2.XorPD(XMM0, "__doublesignbit", sourceIsIndirect: true);
|
XS.SSE2.XorPD(XMM0, "__doublesignbit", sourceIsIndirect: true);
|
||||||
XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true);
|
XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true);
|
||||||
|
|
||||||
#if false
|
|
||||||
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64);
|
|
||||||
XS.FPU.FloatNegate();
|
|
||||||
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -51,24 +43,11 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
{
|
{
|
||||||
if (xStackContentIsFloat)
|
if (xStackContentIsFloat)
|
||||||
{
|
{
|
||||||
#if true
|
|
||||||
if (varDone == false)
|
|
||||||
{
|
|
||||||
XS.DataMember("__floatsignbit", 0x80000000);
|
|
||||||
varDone = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// There is no direct float negate instruction in SSE simply we do a XOR with 0x80000000 to flip the sign bit
|
// There is no direct float negate instruction in SSE simply we do a XOR with 0x80000000 to flip the sign bit
|
||||||
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
|
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
|
||||||
XS.SSE.MoveSS(XMM1, "__floatsignbit", sourceIsIndirect: true);
|
XS.SSE.MoveSS(XMM1, "__floatsignbit", sourceIsIndirect: true);
|
||||||
XS.SSE.XorPS(XMM0, XMM1);
|
XS.SSE.XorPS(XMM0, XMM1);
|
||||||
XS.SSE.MoveSS(ESP, XMM0, destinationIsIndirect: true);
|
XS.SSE.MoveSS(ESP, XMM0, destinationIsIndirect: true);
|
||||||
#if false
|
|
||||||
XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Int32);
|
|
||||||
XS.FPU.FloatNegate();
|
|
||||||
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Int32);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -48,17 +48,18 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
XS.Jump(CPUx86.ConditionalTestEnum.AboveOrEqual, LowPartIsZero);
|
XS.Jump(CPUx86.ConditionalTestEnum.AboveOrEqual, LowPartIsZero);
|
||||||
|
|
||||||
// shift higher part
|
// shift higher part
|
||||||
|
|
||||||
XS.ShiftLeftDouble(ESP, EAX, CL, destinationDisplacement: 4);
|
XS.ShiftLeftDouble(ESP, EAX, CL, destinationDisplacement: 4);
|
||||||
// shift lower part
|
// shift lower part
|
||||||
XS.ShiftLeft(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
|
// To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft!
|
||||||
|
XS.ShiftLeftArithmetic(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
|
||||||
XS.Jump(End_Shl);
|
XS.Jump(End_Shl);
|
||||||
|
|
||||||
XS.Label(LowPartIsZero);
|
XS.Label(LowPartIsZero);
|
||||||
// remove bits >= 32, so that CL max value could be only 31
|
// remove bits >= 32, so that CL max value could be only 31
|
||||||
XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);
|
XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);
|
||||||
// shift low part in EAX and move it in high part
|
// shift low part in EAX and move it in high part
|
||||||
XS.ShiftLeft(EAX, CL);
|
// To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft!
|
||||||
|
XS.ShiftLeftArithmetic(EAX, CL);
|
||||||
XS.Set(ESP, EAX, destinationDisplacement: 4);
|
XS.Set(ESP, EAX, destinationDisplacement: 4);
|
||||||
// replace unknown low part with a zero, if <= 32
|
// replace unknown low part with a zero, if <= 32
|
||||||
XS.Set(XSRegisters.ESP, 0, destinationIsIndirect: true);
|
XS.Set(XSRegisters.ESP, 0, destinationIsIndirect: true);
|
||||||
|
|
|
||||||
|
|
@ -60,16 +60,17 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
XS.Jump(End_Shr);
|
XS.Jump(End_Shr);
|
||||||
|
|
||||||
XS.Label(HighPartIsZero);
|
XS.Label(HighPartIsZero);
|
||||||
|
|
||||||
// remove bits >= 32, so that CL max value could be only 31
|
// remove bits >= 32, so that CL max value could be only 31
|
||||||
XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);
|
XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);
|
||||||
|
|
||||||
// shift high part and move it in low part
|
// shift high part and move it in low part
|
||||||
// To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
|
// To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
|
||||||
//XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL);
|
XS.ShiftRightArithmetic(XSRegisters.EAX, XSRegisters.CL);
|
||||||
XS.ShiftRightArithmetic(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
|
|
||||||
XS.Set(ESP, EAX, destinationIsIndirect: true);
|
XS.Set(ESP, EAX, destinationIsIndirect: true);
|
||||||
// replace unknown high part with a zero, if <= 32
|
// replace unknown high part with a zero
|
||||||
new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};
|
XS.Set(ESP, 0, destinationIsIndirect: true, destinationDisplacement: 4);
|
||||||
|
//new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};
|
||||||
|
|
||||||
XS.Label(End_Shr);
|
XS.Label(End_Shr);
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +95,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
// shift high part
|
// shift high part
|
||||||
XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
|
XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
|
||||||
}*/
|
}*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
// shift high part and move it in low part
|
// shift high part and move it in low part
|
||||||
XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL);
|
XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL);
|
||||||
XS.Set(ESP, EAX, destinationIsIndirect: true);
|
XS.Set(ESP, EAX, destinationIsIndirect: true);
|
||||||
// replace unknown high part with a zero, if <= 32
|
// replace unknown high part with a zero
|
||||||
new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};
|
new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};
|
||||||
|
|
||||||
XS.Label(End_Shr);
|
XS.Label(End_Shr);
|
||||||
|
|
|
||||||
|
|
@ -58,23 +58,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
||||||
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
||||||
XS.SSE2.SubSD(XMM1, XMM0);
|
XS.SSE2.SubSD(XMM1, XMM0);
|
||||||
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
|
XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true);
|
||||||
#if false
|
|
||||||
new FloatLoad
|
|
||||||
{
|
|
||||||
DestinationReg = RegistersEnum.ESP,
|
|
||||||
Size = 64,
|
|
||||||
DestinationIsIndirect = true,
|
|
||||||
DestinationDisplacement = 8
|
|
||||||
};
|
|
||||||
new FloatSub
|
|
||||||
{
|
|
||||||
DestinationReg = RegistersEnum.ESP,
|
|
||||||
DestinationIsIndirect = true,
|
|
||||||
Size = 64
|
|
||||||
};
|
|
||||||
XS.Add(ESP, 8);
|
|
||||||
XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
using Cosmos.Common;
|
||||||
using Cosmos.IL2CPU.Plugs;
|
using Cosmos.IL2CPU.Plugs;
|
||||||
|
|
||||||
namespace Cosmos.System.Plugs.System
|
namespace Cosmos.System.Plugs.System
|
||||||
|
|
@ -9,97 +10,7 @@ namespace Cosmos.System.Plugs.System
|
||||||
{
|
{
|
||||||
public static string ToString(ref double aThis)
|
public static string ToString(ref double aThis)
|
||||||
{
|
{
|
||||||
if (aThis == 0.0)
|
return StringHelper.GetNumberString(aThis);
|
||||||
{
|
|
||||||
return "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
double val = aThis;
|
|
||||||
|
|
||||||
long hexVal = BitConverter.DoubleToInt64Bits(val);
|
|
||||||
long mantissa = (hexVal & 0x1FFFFFFFFFFFFF) | 0x10000000000000;
|
|
||||||
int exp2 = (int) (((hexVal >> 52) & 0x07FF) - 1023);
|
|
||||||
long intPart = 0, fracPart = 0;
|
|
||||||
|
|
||||||
if (exp2 >= 63)
|
|
||||||
{
|
|
||||||
return "Double Overrange";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp2 < -52)
|
|
||||||
{
|
|
||||||
return "Double Underrange";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp2 >= 52)
|
|
||||||
{
|
|
||||||
intPart = mantissa << (exp2 - 52);
|
|
||||||
}
|
|
||||||
else if (exp2 >= 0)
|
|
||||||
{
|
|
||||||
intPart = mantissa >> (52 - exp2);
|
|
||||||
fracPart = (mantissa << (exp2 + 1)) & 0x1FFFFFFFFFFFFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fracPart = (mantissa & 0x1FFFFFFFFFFFFF) >> (-(exp2 + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
string result = "";
|
|
||||||
if (hexVal < 0)
|
|
||||||
{
|
|
||||||
result += "-";
|
|
||||||
}
|
|
||||||
result += intPart.ToString();
|
|
||||||
int usedDigits = result.Length;
|
|
||||||
if (fracPart == 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result += ".";
|
|
||||||
|
|
||||||
if (usedDigits >= 15)
|
|
||||||
{
|
|
||||||
usedDigits = 14;
|
|
||||||
}
|
|
||||||
for (int m = usedDigits; m < 15; m++)
|
|
||||||
{
|
|
||||||
fracPart = (fracPart << 3) + (fracPart << 1);
|
|
||||||
char p = (char) (((fracPart >> 53) & 0xFF) + '0');
|
|
||||||
result += p;
|
|
||||||
|
|
||||||
fracPart &= 0x1FFFFFFFFFFFFF;
|
|
||||||
}
|
|
||||||
fracPart = (fracPart << 3) + (fracPart << 1);
|
|
||||||
char remain = (char) ((fracPart >> 53) + '0');
|
|
||||||
if ((remain > '5') && (result[result.Length - 1] > '0'))
|
|
||||||
{
|
|
||||||
char[] answer = result.ToCharArray();
|
|
||||||
int digitPos = answer.Length - 1;
|
|
||||||
char digit = result[digitPos];
|
|
||||||
answer[digitPos] = (char) (digit + 1);
|
|
||||||
while (answer[digitPos] > '9')
|
|
||||||
{
|
|
||||||
answer[digitPos] = '0';
|
|
||||||
digitPos--;
|
|
||||||
digit = result[digitPos];
|
|
||||||
if (digit == '.')
|
|
||||||
{
|
|
||||||
digitPos--;
|
|
||||||
digit = result[digitPos];
|
|
||||||
}
|
|
||||||
answer[digitPos] = (char) (digit + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = new string(answer);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (result[result.Length - 1] == '0')
|
|
||||||
{
|
|
||||||
result = result.Substring(0, result.Length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,108 +1,16 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
using Cosmos.Common;
|
||||||
using Cosmos.IL2CPU.Plugs;
|
using Cosmos.IL2CPU.Plugs;
|
||||||
|
|
||||||
namespace Cosmos.System.Plugs.System
|
namespace Cosmos.System.Plugs.System
|
||||||
{
|
{
|
||||||
[Plug(Target = typeof(float))]
|
[Plug(Target = typeof(float))]
|
||||||
public static class SingleImpl
|
public static class SingleImpl
|
||||||
{
|
{
|
||||||
public static string ToString(ref float aThis)
|
public static string ToString(ref float aThis)
|
||||||
{
|
{
|
||||||
if (aThis == 0.0f)
|
return StringHelper.GetNumberString(aThis);
|
||||||
{
|
|
||||||
return "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
float xValue = aThis;
|
|
||||||
|
|
||||||
var singleBytes = BitConverter.GetBytes(xValue);
|
|
||||||
int hexVal = BitConverter.ToInt32(singleBytes, 0);
|
|
||||||
int intPart = 0, fracPart = 0;
|
|
||||||
|
|
||||||
int exp2 = ((hexVal >> 23) & 0xFF) - 127;
|
|
||||||
int mantissa = (hexVal & 0xFFFFFF) | 0x800000;
|
|
||||||
|
|
||||||
if (exp2 >= 31)
|
|
||||||
{
|
|
||||||
return "Single Overrange";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp2 < -23)
|
|
||||||
{
|
|
||||||
return "Single Underrange";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exp2 >= 23)
|
|
||||||
{
|
|
||||||
intPart = mantissa << (exp2 - 23);
|
|
||||||
}
|
|
||||||
else if (exp2 >= 0)
|
|
||||||
{
|
|
||||||
intPart = mantissa >> (23 - exp2);
|
|
||||||
fracPart = (mantissa << (exp2 + 1)) & 0xFFFFFF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fracPart = (mantissa & 0xFFFFFF) >> (-(exp2 + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
string result = "";
|
|
||||||
if (hexVal < 0)
|
|
||||||
{
|
|
||||||
result += "-";
|
|
||||||
}
|
|
||||||
result += ((uint)intPart).ToString();
|
|
||||||
int usedDigits = ((uint)intPart).ToString().Length;
|
|
||||||
if (fracPart == 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result += ".";
|
|
||||||
|
|
||||||
if (usedDigits >= 7)
|
|
||||||
{
|
|
||||||
usedDigits = 6;
|
|
||||||
}
|
|
||||||
for (int m = usedDigits; m < 7; m++)
|
|
||||||
{
|
|
||||||
fracPart = (fracPart << 3) + (fracPart << 1);
|
|
||||||
char p = (char)((fracPart >> 24) + '0');
|
|
||||||
result += p;
|
|
||||||
|
|
||||||
fracPart &= 0xFFFFFF;
|
|
||||||
}
|
|
||||||
fracPart = (fracPart << 3) + (fracPart << 1);
|
|
||||||
char remain = (char)((fracPart >> 24) + '0');
|
|
||||||
if ((remain > '5') && (result[result.Length - 1] > '0'))
|
|
||||||
{
|
|
||||||
char[] answer = result.ToCharArray();
|
|
||||||
int digitPos = answer.Length - 1;
|
|
||||||
char digit = result[digitPos];
|
|
||||||
answer[digitPos] = (char)(digit + 1);
|
|
||||||
while (answer[digitPos] > '9')
|
|
||||||
{
|
|
||||||
answer[digitPos] = '0';
|
|
||||||
digitPos--;
|
|
||||||
digit = result[digitPos];
|
|
||||||
if (digit == '.')
|
|
||||||
{
|
|
||||||
digitPos--;
|
|
||||||
digit = result[digitPos];
|
|
||||||
}
|
|
||||||
answer[digitPos] = (char)(digit + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = new string(answer);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (result[result.Length - 1] == '0')
|
|
||||||
{
|
|
||||||
result = result.Substring(0, result.Length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue