add movsx, fchs

implement neg CIL (needed for Abs())
fix floor and ceiling in range of int
add sign extension to LdArg and LdLoc
remove unneeded math functions, like min,max,abs
This commit is contained in:
Trivalik_cp 2011-09-02 21:03:14 +00:00
parent bcd92cf77c
commit 51e893eb74
8 changed files with 127 additions and 208 deletions

View file

@ -64,6 +64,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="MoveSignExtend.cs" />
<Compile Include="Lgdt.cs" />
<Compile Include="Lidt.cs" />
<Compile Include="Shrd.cs" />
@ -75,6 +76,7 @@
<Compile Include="SignExtendAX.cs" />
<Compile Include="CmpXchg.cs" />
<Compile Include="CpuId.cs" />
<Compile Include="x87\FloatNegate.cs" />
<Compile Include="XchgAndAdd.cs" />
<Compile Include="Add.cs" />
<Compile Include="AddWithCarry.cs" />

View file

@ -0,0 +1,24 @@
namespace Cosmos.Compiler.Assembler.X86 {
[OpCode("movsx")]
public class MoveSignExtend : InstructionWithDestinationAndSourceAndSize
{
public override void WriteText(Assembler aAssembler, System.IO.TextWriter aOutput)
{
if (Size == 0)
{
Size = 32;
}
aOutput.Write(mMnemonic);
if (!DestinationEmpty)
{
aOutput.Write(" ");
aOutput.Write(this.GetDestinationAsString());
aOutput.Write(", ");
aOutput.Write(SizeToString(Size));
aOutput.Write(" ");
aOutput.Write(this.GetSourceAsString());
}
}
}
}

View file

@ -0,0 +1,7 @@
namespace Cosmos.Compiler.Assembler.X86.x87
{
[OpCode("fchs")]
public class FloatNegate : Instruction
{
}
}

View file

@ -3,6 +3,7 @@ using Cosmos.IL2CPU.ILOpCodes;
using Cosmos.IL2CPU.X86;
using Cosmos.Compiler.Assembler;
using Cosmos.Compiler.Assembler.X86;
using CPUx86 = Cosmos.Compiler.Assembler.X86;
namespace Cosmos.IL2CPU.X86.IL
{
@ -83,7 +84,6 @@ namespace Cosmos.IL2CPU.X86.IL
}
public static void DoExecute(Assembler Assembler, MethodInfo aMethod, ushort aParam) {
uint xArgSize = 0u;
var xDisplacement = GetArgumentDisplacement(aMethod, aParam);
Type xArgType;
if (aMethod.MethodBase.IsStatic) {
@ -101,16 +101,25 @@ namespace Cosmos.IL2CPU.X86.IL
}
new Comment("Ldarg");
new Comment("Arg idx = " + aParam);
xArgSize = Align(SizeOfType(xArgType), 4);
new Comment("Arg type = " + xArgType.ToString());
new Comment("Arg size = " + xArgSize);
for (int i = 0; i < (xArgSize / 4); i++) {
new Push {
DestinationReg = Registers.EBP,
DestinationIsIndirect = true,
DestinationDisplacement = (int)(xDisplacement - (i * 4))
};
}
uint xArgRealSize = SizeOfType(xArgType);
uint xArgSize = Align(xArgRealSize, 4);
new Comment("Arg type = " + xArgType.ToString());
new Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize);
if (xArgRealSize < 4)
{
new CPUx86.MoveSignExtend { DestinationReg = CPUx86.Registers.EAX, Size = (byte)(xArgRealSize * 8), SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = xDisplacement };
new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
}
else
{
for (int i = 0; i < (xArgSize / 4); i++) {
new Push {
DestinationReg = Registers.EBP,
DestinationIsIndirect = true,
DestinationDisplacement = xDisplacement - (i * 4)
};
}
}
Assembler.Stack.Push(xArgSize, xArgType);
}
}

View file

@ -34,16 +34,9 @@ namespace Cosmos.IL2CPU.X86.IL
switch (xSize)
{
case 1:
{
new CPUx86.Xor { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.AL, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0 - xEBPOffset };
new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
break;
}
case 2:
{
new CPUx86.Xor { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.AX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0 - xEBPOffset };
new CPUx86.MoveSignExtend { DestinationReg = CPUx86.Registers.EAX, Size = (byte)(xSize * 8), SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0 - xEBPOffset };
new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
break;
}
@ -53,13 +46,8 @@ namespace Cosmos.IL2CPU.X86.IL
break;
}
}
}
#if DOTNETCOMPATIBLE
Assembler.Stack.Push(ILOp.Align(xSize, 4), xVar.LocalType);
#else
Assembler.Stack.Push(xSize, xVar.LocalType);
#endif
}
}
}

View file

@ -1,6 +1,5 @@
using System;
using CPUx86 = Cosmos.Compiler.Assembler.X86;
using Cosmos.Compiler.Assembler.X86;
using Label = Cosmos.Compiler.Assembler.Label;
namespace Cosmos.IL2CPU.X86.IL
{
@ -19,10 +18,10 @@ namespace Cosmos.IL2CPU.X86.IL
{
if (xStackContent.IsFloat)
{
new CPUx86.x87.FloatLoad { DestinationReg = Registers.ESP, Size = 64, DestinationIsIndirect = true };
new CPUx86.Add { SourceValue = 8, DestinationReg = Registers.ESP };
new CPUx86.x87.FloatLoad { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true };
new CPUx86.Add { SourceValue = 8, DestinationReg = CPUx86.Registers.ESP };
new CPUx86.x87.FloatMul { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, Size = 64 };
new CPUx86.x87.FloatStoreAndPop { DestinationReg = Registers.ESP, Size = 64, DestinationIsIndirect = true };
new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true };
}
else
{
@ -47,7 +46,7 @@ namespace Cosmos.IL2CPU.X86.IL
//mov RIGHT_HIGH to eax, is useable on Full 64 multiply
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4 };
new CPUx86.Compare { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12 };
new CPUx86.ConditionalJump { Condition = ConditionalTestEnum.Zero, DestinationLabel = Simple32Multiply };
new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = Simple32Multiply };
// Full 64 Multiply
// eax contains already RIGHT_HIGH

View file

@ -3,20 +3,51 @@ using CPUx86 = Cosmos.Compiler.Assembler.X86;
namespace Cosmos.IL2CPU.X86.IL
{
[Cosmos.IL2CPU.OpCode( ILOpCode.Code.Neg )]
public class Neg : ILOp
{
public Neg( Cosmos.Compiler.Assembler.Assembler aAsmblr )
: base( aAsmblr )
{
}
[Cosmos.IL2CPU.OpCode( ILOpCode.Code.Neg )]
public class Neg : ILOp
{
public Neg( Cosmos.Compiler.Assembler.Assembler aAsmblr )
: base( aAsmblr )
{
}
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode )
{
new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX };
new CPUx86.Neg { DestinationReg = CPUx86.Registers.EAX };
new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
}
}
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode )
{
var xStackContent = Assembler.Stack.Peek();
if (xStackContent.Size > 4)
{
if (xStackContent.IsFloat)
{
new CPUx86.x87.FloatLoad { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true };
new CPUx86.x87.FloatNegate { };
new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true };
}
else
{
new CPUx86.Pop { DestinationReg = CPUx86.Registers.EBX }; // low
new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; // high
new CPUx86.Neg { DestinationReg = CPUx86.Registers.EBX }; // set carry if EBX != 0
new CPUx86.AddWithCarry { DestinationReg = CPUx86.Registers.EAX, SourceValue = 0 };
new CPUx86.Neg { DestinationReg = CPUx86.Registers.EAX };
new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
new CPUx86.Push { DestinationReg = CPUx86.Registers.EBX };
}
}
else
{
if (xStackContent.IsFloat)
{
new CPUx86.x87.FloatLoad { DestinationReg = CPUx86.Registers.ESP, Size = 32, DestinationIsIndirect = true };
new CPUx86.x87.FloatNegate { };
new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.Registers.ESP, Size = 32, DestinationIsIndirect = true };
}
else
{
new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX };
new CPUx86.Neg { DestinationReg = CPUx86.Registers.EAX };
new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
}
}
}
}
}

View file

@ -12,6 +12,7 @@ namespace Cosmos.System.Plugs.System
public const double PI = 3.14159265358979;
public const double E = 2.71828182845905;
// TODO Abs decimal
#region Abs
public static double Abs(double value)
{
@ -37,6 +38,7 @@ namespace Cosmos.System.Plugs.System
}
}
/* should work from ms .net
public static long Abs(long value)
{
if (value < 0)
@ -59,23 +61,13 @@ namespace Cosmos.System.Plugs.System
{
return value;
}
}
}*/
#endregion
// TODO Max decimal
#region Max
public static byte Max(byte val1, byte val2)
{
if (val1 > val2)
{
return val1;
}
else
{
return val2;
}
}
//public static decimal Max(decimal val1, decimal val2)
//public static decimal Max(decimal val1, decimal val2)
//{
// if (val1 > val2)
// {
@ -87,79 +79,10 @@ namespace Cosmos.System.Plugs.System
// }
//}
public static double Max(double val1, double val2)
{
if (val1 > val2)
{
return val1;
}
else
{
return val2;
}
}
public static short Max(short val1, short val2)
{
if (val1 > val2)
{
return val1;
}
else
{
return val2;
}
}
public static int Max(int val1, int val2)
{
if (val1 > val2)
{
return val1;
}
else
{
return val2;
}
}
public static long Max(long val1, long val2)
{
if (val1 > val2)
{
return val1;
}
else
{
return val2;
}
}
public static float Max(float val1, float val2)
{
if (val1 > val2)
{
return val1;
}
else
{
return val2;
}
}
#endregion
//TODO Min decimal
#region Min
public static byte Min(byte val1, byte val2)
{
if (val1 < val2)
{
return val1;
}
else
{
return val2;
}
}
//public static decimal Min(decimal val1, decimal val2)
//{
@ -173,65 +96,6 @@ namespace Cosmos.System.Plugs.System
// }
//}
public static double Min(double val1, double val2)
{
if (val1 < val2)
{
return val1;
}
else
{
return val2;
}
}
public static short Min(short val1, short val2)
{
if (val1 < val2)
{
return val1;
}
else
{
return val2;
}
}
public static int Min(int val1, int val2)
{
if (val1 < val2)
{
return val1;
}
else
{
return val2;
}
}
public static long Min(long val1, long val2)
{
if (val1 < val2)
{
return val1;
}
else
{
return val2;
}
}
public static float Min(float val1, float val2)
{
if (val1 < val2)
{
return val1;
}
else
{
return val2;
}
}
#endregion
#region Pow
@ -261,7 +125,7 @@ namespace Cosmos.System.Plugs.System
#region Sin
public static double Sin(double a)
{
{ // should be using assembler instruction
bool signSwitch = false;
double result = 0;
@ -283,8 +147,6 @@ namespace Cosmos.System.Plugs.System
result = (radians) - (Math.Pow(radians, 3) / Factorial(3));
result += (Math.Pow(radians, 5) / Factorial(5)) - (Math.Pow(radians, 7) / Factorial(7)) + (Math.Pow(radians, 9) / Factorial(9));
//result *= -1;
/* USE WHEN Modulus Works
* int sign = 0;
for (int i = 3; i < 19; i += 2)
@ -318,7 +180,7 @@ namespace Cosmos.System.Plugs.System
}
#endregion
#region Factorial
#region Factorial (only used in Sin(), not plug )
public static int Factorial(int n)
{
if (n == 0)
@ -329,26 +191,23 @@ namespace Cosmos.System.Plugs.System
#endregion
#region Ceiling
public static double Ceiling(double a)
{
int returnval = (int)Floor(a);
returnval += 1;
return returnval;
}
public static double Ceiling(double a)
{ // should be using assembler for bigger values than int or long max
if (a == Double.NaN || a == Double.NegativeInfinity || a == Double.PositiveInfinity)
return a;
int i = (a - (int)a > 0) ? (int)(a + 1) : (int)a;
return i;
}
#endregion
#region Floor
public static double Floor(double a)
{
int returnval = (int)a;
if (a < 0)
{
returnval -= 1;
}
return returnval;
}
public static double Floor(double a)
{ // should be using assembler for bigger values than int or long max
if (a == Double.NaN || a == Double.NegativeInfinity || a == Double.PositiveInfinity)
return a;
int i = (a - (int)a < 0) ? (int)(a - 1) : (int)a;
return i;
}
#endregion
}
}