mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-27 22:12:25 +00:00
commit
552ded82b8
30 changed files with 547 additions and 565 deletions
|
|
@ -17,11 +17,12 @@
|
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
|
|
@ -85,6 +86,7 @@
|
|||
<Compile Include="System\BooleanTest.cs" />
|
||||
<Compile Include="System\ByteTest.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\QueueTest.cs" />
|
||||
<Compile Include="System\DecimalTest.cs" />
|
||||
|
|
@ -100,6 +102,7 @@
|
|||
<Compile Include="System\UInt16Test.cs" />
|
||||
<Compile Include="System\UInt32Test.cs" />
|
||||
<Compile Include="System\UInt64Test.cs" />
|
||||
<Compile Include="System\UnsafeCodeTest.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Cosmos.TestRunner.TestController\Cosmos.TestRunner.TestController.csproj">
|
||||
|
|
|
|||
|
|
@ -37,12 +37,11 @@ namespace Cosmos.Compiler.Tests.Bcl
|
|||
BooleanTest.Execute();
|
||||
SingleTest.Execute();
|
||||
DoubleTest.Execute();
|
||||
|
||||
#if false
|
||||
BitConverterTest.Execute();
|
||||
UnsafeCodeTest.Execute();
|
||||
|
||||
#if false
|
||||
DecimalTest.Execute();
|
||||
//BitConverterTest.Execute();
|
||||
//DecimalTest.Execute();
|
||||
System.Collections.Generic.ListTest.Execute();
|
||||
System.Collections.Generic.QueueTest.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);
|
||||
|
||||
|
||||
long aLong = 1;
|
||||
|
||||
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:
|
||||
public static void Execute()
|
||||
{
|
||||
#if false
|
||||
|
||||
Decimal value;
|
||||
String result;
|
||||
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?
|
||||
|
||||
#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
|
||||
result = value.ToString();
|
||||
expectedResult = "42.42";
|
||||
|
|
|
|||
|
|
@ -26,31 +26,63 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
|||
String result;
|
||||
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?
|
||||
|
||||
// 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));
|
||||
/* First start with some weird value (not really numbers) that the IEEE standard has */
|
||||
value = Double.PositiveInfinity;
|
||||
|
||||
result = value.ToString();
|
||||
expectedResult = "1";
|
||||
expectedResult = "∞";
|
||||
|
||||
// The test fails the conversion returns "Double Underrange"
|
||||
Assert.IsTrue((result == expectedResult), "Double.ToString doesn't work");
|
||||
Assert.IsTrue((result == expectedResult), "Double.ToString of INF 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
|
||||
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");
|
||||
|
||||
|
|
@ -59,14 +91,14 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
|||
// Actually 'expectedResult' should be the same so...
|
||||
Assert.IsTrue((result == expectedResult), "String format (Double) doesn't work");
|
||||
|
||||
#if false
|
||||
// Now let's Get the HashCode of a value
|
||||
int resultAsInt = value.GetHashCode();
|
||||
|
||||
// actually the Hash Code of a Int32 is the same value
|
||||
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!)
|
||||
result = value.ToString("X2");
|
||||
expectedResult = "0x7FFFFFFF";
|
||||
|
|
@ -163,22 +195,9 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
|||
Assert.IsTrue((DoublesAreEqual(valueNegated, 42d)), "(double) negation doesn't work");
|
||||
|
||||
// Let's try if it works in the other way too
|
||||
//value = 42.0;
|
||||
//valueNegated = -value;
|
||||
//Assert.IsTrue((DoublesAreEqual(valueNegated, -42.0f)), "(double) negation of positive float 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
|
||||
value = 42.0;
|
||||
valueNegated = -value;
|
||||
Assert.IsTrue((DoublesAreEqual(valueNegated, -42.0f)), "(double) negation of positive double doesn't work");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,24 +18,24 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
|||
result = value.ToString();
|
||||
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
|
||||
result = "The Maximum value of an Int32 is " + value;
|
||||
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 '+'
|
||||
result = $"The Maximum value of an Int32 is {value}";
|
||||
// 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
|
||||
int resultAsInt = value.GetHashCode();
|
||||
|
||||
// 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
|
||||
// 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");
|
||||
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
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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)
|
||||
return true;
|
||||
|
|
@ -19,38 +19,65 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
|||
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()
|
||||
{
|
||||
Single value;
|
||||
String result;
|
||||
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();
|
||||
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
|
||||
result = "The value of the Single is " + value;
|
||||
|
|
@ -101,42 +128,35 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
|||
Single otherValue = 2.20f;
|
||||
|
||||
OperationResult = value + otherValue;
|
||||
//expectedResult = "44.62";
|
||||
|
||||
Assert.IsTrue((SinglesAreEqual(OperationResult, 44.62f)), "float operator+ doesn't work");
|
||||
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator+ doesn't work");
|
||||
|
||||
// Now test subtraction
|
||||
OperationResult = value - otherValue;
|
||||
//expectedResult = "40.22";
|
||||
|
||||
Assert.IsTrue((SinglesAreEqual(OperationResult, 40.22f)), "float operator- doesn't work");
|
||||
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator- doesn't work");
|
||||
|
||||
// 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...
|
||||
OperationResult = value * otherValue;
|
||||
//expectedResult = "84.84";
|
||||
|
||||
Assert.IsTrue((SinglesAreEqual(OperationResult, 84.84f)), "float operator* doesn't work");
|
||||
//Assert.IsTrue((OperationResult.ToString() == expectedResult), "float operator* doesn't work");
|
||||
|
||||
// Now test division
|
||||
OperationResult = value / otherValue;
|
||||
//expectedResult = "21.21";
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
byte valueAsByte = (byte)value;
|
||||
|
|
@ -178,31 +198,14 @@ namespace Cosmos.Compiler.Tests.Bcl.System
|
|||
value = (float)anULong;
|
||||
Assert.IsTrue((SinglesAreEqual(value, 9223372036854775849f)), "(float) from ulong operator doesn't work");
|
||||
|
||||
//value = -42.0f;
|
||||
//float valueNegated = -value;
|
||||
//Assert.IsTrue((SinglesAreEqual(valueNegated, 42.0f)), "(float) negation doesn't work");
|
||||
value = -42.0f;
|
||||
float valueNegated = -value;
|
||||
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
|
||||
value = 42.0f;
|
||||
valueNegated = -value;
|
||||
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 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';
|
||||
string y = "a";
|
||||
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");
|
||||
|
||||
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
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Cosmos.Common
|
||||
{
|
||||
|
|
@ -131,6 +127,254 @@ namespace Cosmos.Common
|
|||
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)
|
||||
{
|
||||
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(@"__ulong2double_const", 0x5F800000));
|
||||
DataMembers.Add(new DataMember(@"__doublesignbit", 0x8000000000000000));
|
||||
//DataMembers.Add(new DataMember(@"__floatsignbit", 0x80000000));
|
||||
DataMembers.Add(new DataMember(@"__floatsignbit", 0x80000000));
|
||||
|
||||
if (mComPort > 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,13 +44,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
|||
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
||||
XS.SSE2.AddSD(XMM1, XMM0);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
XS.Add(ESP, 4);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
XS.Add(ESP, 4);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
XS.Add(ESP, 4);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
XS.Add(ESP, 4);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
XS.Add(ESP, 4);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,18 +35,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
|||
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
||||
XS.SSE2.DivSD(XMM1, XMM0);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 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.EAX, XSRegisters.EBP);
|
||||
XS.Add(XSRegisters.EAX, XSRegisters.EBX);
|
||||
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.MulSD(XMM1, XMM0);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
|||
[Cosmos.IL2CPU.OpCode( ILOpCode.Code.Neg )]
|
||||
public class Neg : ILOp
|
||||
{
|
||||
static bool varDone = false;
|
||||
|
||||
public Neg( Cosmos.Assembler.Assembler aAsmblr )
|
||||
: base( aAsmblr )
|
||||
{
|
||||
|
|
@ -29,12 +27,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
|||
XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true);
|
||||
XS.SSE2.XorPD(XMM0, "__doublesignbit", sourceIsIndirect: 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
|
||||
{
|
||||
|
|
@ -51,24 +43,11 @@ namespace Cosmos.IL2CPU.X86.IL
|
|||
{
|
||||
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
|
||||
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
|
||||
XS.SSE.MoveSS(XMM1, "__floatsignbit", sourceIsIndirect: true);
|
||||
XS.SSE.XorPS(XMM0, XMM1);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,17 +48,18 @@ namespace Cosmos.IL2CPU.X86.IL
|
|||
XS.Jump(CPUx86.ConditionalTestEnum.AboveOrEqual, LowPartIsZero);
|
||||
|
||||
// shift higher part
|
||||
|
||||
XS.ShiftLeftDouble(ESP, EAX, CL, destinationDisplacement: 4);
|
||||
// shift lower part
|
||||
XS.ShiftLeft(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32);
|
||||
// shift lower part
|
||||
// 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.Label(LowPartIsZero);
|
||||
// remove bits >= 32, so that CL max value could be only 31
|
||||
XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);
|
||||
// shift low part in EAX and move it in high part
|
||||
XS.ShiftLeft(EAX, CL);
|
||||
// shift low part in EAX and move it in high part
|
||||
// To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft!
|
||||
XS.ShiftLeftArithmetic(EAX, CL);
|
||||
XS.Set(ESP, EAX, destinationDisplacement: 4);
|
||||
// replace unknown low part with a zero, if <= 32
|
||||
XS.Set(XSRegisters.ESP, 0, destinationIsIndirect: true);
|
||||
|
|
|
|||
|
|
@ -60,16 +60,17 @@ namespace Cosmos.IL2CPU.X86.IL
|
|||
XS.Jump(End_Shr);
|
||||
|
||||
XS.Label(HighPartIsZero);
|
||||
|
||||
// remove bits >= 32, so that CL max value could be only 31
|
||||
XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8);
|
||||
|
||||
// shift high part and move it in low part
|
||||
// To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight!
|
||||
//XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL);
|
||||
XS.ShiftRightArithmetic(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
|
||||
XS.ShiftRightArithmetic(XSRegisters.EAX, XSRegisters.CL);
|
||||
XS.Set(ESP, EAX, destinationIsIndirect: true);
|
||||
// replace unknown high part with a zero, if <= 32
|
||||
new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0};
|
||||
// replace unknown high part with a zero
|
||||
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);
|
||||
}
|
||||
|
|
@ -94,6 +95,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
|||
// shift high part
|
||||
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
|
||||
XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL);
|
||||
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.Label(End_Shr);
|
||||
|
|
|
|||
|
|
@ -58,23 +58,6 @@ namespace Cosmos.IL2CPU.X86.IL
|
|||
XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true);
|
||||
XS.SSE2.SubSD(XMM1, XMM0);
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
|
||||
using Cosmos.Common;
|
||||
using Cosmos.IL2CPU.Plugs;
|
||||
|
||||
namespace Cosmos.System.Plugs.System
|
||||
|
|
@ -9,97 +10,7 @@ namespace Cosmos.System.Plugs.System
|
|||
{
|
||||
public static string ToString(ref double aThis)
|
||||
{
|
||||
if (aThis == 0.0)
|
||||
{
|
||||
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;
|
||||
return StringHelper.GetNumberString(aThis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,108 +1,16 @@
|
|||
using System;
|
||||
|
||||
using Cosmos.Common;
|
||||
using Cosmos.IL2CPU.Plugs;
|
||||
|
||||
namespace Cosmos.System.Plugs.System
|
||||
{
|
||||
[Plug(Target = typeof(float))]
|
||||
public static class SingleImpl
|
||||
{
|
||||
{
|
||||
public static string ToString(ref float aThis)
|
||||
{
|
||||
if (aThis == 0.0f)
|
||||
{
|
||||
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;
|
||||
return StringHelper.GetNumberString(aThis);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue