This commit is contained in:
Matthijs ter Woord 2016-06-17 08:23:48 -04:00
parent 9d203f141e
commit 4cfc7aabe7
7 changed files with 233 additions and 158 deletions

View file

@ -1,6 +1,7 @@
using System;
using Cosmos.Assembler.x86.SSE;
using XSharp.Compiler;
using static XSharp.Compiler.XSRegisters;
using CPUx86 = Cosmos.Assembler.x86;
using Label = Cosmos.Assembler.Label;
@ -36,7 +37,7 @@ namespace Cosmos.IL2CPU.X86.IL
// override value 1
new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.RegistersEnum.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8 };
// pop value 2
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
}
else
{
@ -47,58 +48,58 @@ namespace Cosmos.IL2CPU.X86.IL
// divisor
//low
XS.Set(XSRegisters.ESI, XSRegisters.ESP, sourceIsIndirect: true);
XS.Set(ESI, ESP, sourceIsIndirect: true);
//high
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
// pop both 8 byte values
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
//dividend
// low
XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceIsIndirect: true);
XS.Set(EAX, ESP, sourceIsIndirect: true);
//high
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EDX), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
// set flags
XS.Or(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI));
XS.Or(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.EDI));
// if high dword of divisor is already zero, we dont need the loop
XS.Jump(CPUx86.ConditionalTestEnum.Zero, LabelNoLoop);
// set ecx to zero for counting the shift operations
XS.Xor(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Xor(OldToNewRegister(CPUx86.RegistersEnum.ECX), OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Label(LabelShiftRight);
// shift divisor 1 bit right
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.RegistersEnum.ESI, SourceReg = CPUx86.RegistersEnum.EDI, ArgumentValue = 1 };
XS.ShiftRight(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), 1);
XS.ShiftRightDouble(ESI, EDI, 1);
XS.ShiftRight(OldToNewRegister(CPUx86.RegistersEnum.EDI), 1);
// increment shift counter
XS.Increment(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Increment(OldToNewRegister(CPUx86.RegistersEnum.ECX));
// set flags
XS.Or(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI));
XS.Or(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.EDI));
// loop while high dword of divisor till it is zero
XS.Jump(CPUx86.ConditionalTestEnum.NotZero, LabelShiftRight);
// shift the divident now in one step
// shift divident CL bits right
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.RegistersEnum.EAX, SourceReg = CPUx86.RegistersEnum.EDX, ArgumentReg = CPUx86.RegistersEnum.CL };
XS.ShiftRight(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.CL);
XS.ShiftRightDouble(EAX, EDX, CL);
XS.ShiftRight(OldToNewRegister(CPUx86.RegistersEnum.EDX), CL);
// so we shifted both, so we have near the same relation as original values
// divide this
XS.IntegerDivide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.IntegerDivide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// sign extend
XS.SignExtendAX(XSRegisters.RegisterSize.Int32);
XS.SignExtendAX(RegisterSize.Int32);
// save result to stack
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EAX));
//TODO: implement proper derivation correction and overflow detection
@ -106,19 +107,19 @@ namespace Cosmos.IL2CPU.X86.IL
XS.Label(LabelNoLoop);
//save high dividend
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.ECX), OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.EDX));
// extend that sign is in edx
XS.SignExtendAX(XSRegisters.RegisterSize.Int32);
XS.SignExtendAX(RegisterSize.Int32);
// divide high part
XS.IntegerDivide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.IntegerDivide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// save high result
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.ECX));
// divide low part
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// save low result
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Label(LabelEnd);
}
@ -127,19 +128,19 @@ namespace Cosmos.IL2CPU.X86.IL
{
if (TypeIsFloat(xStackItem))
{
XS.SSE.MoveSS(XSRegisters.XMM0, XSRegisters.ESP, sourceIsIndirect: true);
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XSRegisters.XMM1, XSRegisters.ESP, sourceIsIndirect: true);
XS.SSE.DivSS(XSRegisters.XMM0, XSRegisters.XMM1);
XS.SSE.MoveSS(XSRegisters.XMM1, XSRegisters.ESP, sourceIsIndirect: true);
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
XS.SSE.DivSS(XMM0, XMM1);
XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
}
else
{
XS.Pop(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Pop(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.SignExtendAX(XSRegisters.RegisterSize.Int32);
XS.IntegerDivide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Pop(OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Pop(OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.SignExtendAX(RegisterSize.Int32);
XS.IntegerDivide(OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EAX));
}
}
}

View file

@ -1,6 +1,7 @@
using System;
using Cosmos.Assembler.x86.SSE;
using XSharp.Compiler;
using static XSharp.Compiler.XSRegisters;
using CPUx86 = Cosmos.Assembler.x86;
using Label = Cosmos.Assembler.Label;
@ -37,7 +38,7 @@ namespace Cosmos.IL2CPU.X86.IL
// override value 1
new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.RegistersEnum.ESP, Size = 64, DestinationIsIndirect = true, DestinationDisplacement = 8 };
// pop value 2
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
}
else
{
@ -48,53 +49,54 @@ namespace Cosmos.IL2CPU.X86.IL
// divisor
//low
XS.Set(XSRegisters.ESI, XSRegisters.ESP, sourceIsIndirect: true);
XS.Set(ESI, ESP, sourceIsIndirect: true);
//high
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
//dividend
// low
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 8);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 8);
//high
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 12);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EDX), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 12);
// pop both 8 byte values
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 16);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 16);
// set flags
XS.Or(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI));
XS.Or(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.EDI));
// if high dword of divisor is already zero, we dont need the loop
XS.Jump(CPUx86.ConditionalTestEnum.Zero, LabelNoLoop);
// set ecx to zero for counting the shift operations
XS.Xor(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Xor(OldToNewRegister(CPUx86.RegistersEnum.ECX), OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Label(LabelShiftRight);
// shift divisor 1 bit right
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.RegistersEnum.ESI, SourceReg = CPUx86.RegistersEnum.EDI, ArgumentValue = 1 };
XS.ShiftRight(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), 1);
XS.ShiftRightDouble(ESI, EDI, 1);
XS.ShiftRight(OldToNewRegister(CPUx86.RegistersEnum.EDI), 1);
// increment shift counter
XS.Increment(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Increment(OldToNewRegister(CPUx86.RegistersEnum.ECX));
// set flags
XS.Or(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI));
XS.Or(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.EDI));
// loop while high dword of divisor till it is zero
XS.Jump(CPUx86.ConditionalTestEnum.NotZero, LabelShiftRight);
// shift the divident now in one step
// shift divident CL bits right
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.RegistersEnum.EAX, SourceReg = CPUx86.RegistersEnum.EDX, ArgumentReg = CPUx86.RegistersEnum.CL };
XS.ShiftRight(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.CL);
XS.ShiftRightDouble(EAX, EDX, CL);
XS.ShiftRight(OldToNewRegister(CPUx86.RegistersEnum.EDX), CL);
// so we shifted both, so we have near the same relation as original values
// divide this
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// save result to stack
XS.Push(0);
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EAX));
//TODO: implement proper derivation correction and overflow detection
@ -103,19 +105,19 @@ namespace Cosmos.IL2CPU.X86.IL
XS.Label(LabelNoLoop);
//save high dividend
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.ECX), OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.EDX));
// zero EDX, so that high part is zero -> reduce overflow case
XS.Xor(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Xor(OldToNewRegister(CPUx86.RegistersEnum.EDX), OldToNewRegister(CPUx86.RegistersEnum.EDX));
// divide high part
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// save high result
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.ECX));
// divide low part
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// save low result
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Label(LabelEnd);
}
@ -124,19 +126,19 @@ namespace Cosmos.IL2CPU.X86.IL
{
if (TypeIsFloat(xStackItem))
{
XS.SSE.MoveSS(XSRegisters.XMM0, XSRegisters.ESP, sourceIsIndirect: true);
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XSRegisters.XMM1, XSRegisters.ESP, sourceIsIndirect: true);
XS.SSE.MulSS(XSRegisters.XMM0, XSRegisters.XMM1);
XS.SSE.MoveSS(XSRegisters.XMM1, XSRegisters.ESP, sourceIsIndirect: true);
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
XS.SSE.MulSS(XMM0, XMM1);
XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
}
else
{
XS.Xor(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Pop(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Pop(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Xor(OldToNewRegister(CPUx86.RegistersEnum.EDX), OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Pop(OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Pop(OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EAX));
}
}
}

View file

@ -3,6 +3,7 @@ using CPUx86 = Cosmos.Assembler.x86;
using Cosmos.Assembler;
using Cosmos.Assembler.x86.SSE;
using XSharp.Compiler;
using static XSharp.Compiler.XSRegisters;
namespace Cosmos.IL2CPU.X86.IL
{
@ -22,12 +23,12 @@ namespace Cosmos.IL2CPU.X86.IL
{
if (TypeIsFloat( xStackItem))
{
XS.SSE.MoveSS(XSRegisters.XMM0, XSRegisters.ESP, sourceIsIndirect: true);
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
XS.SSE.MoveSS(XSRegisters.XMM1, XSRegisters.ESP, sourceIsIndirect: true);
XS.SSE.XorPS(XSRegisters.XMM2, XSRegisters.XMM2);
XS.SSE.DivPS(XSRegisters.XMM1, XSRegisters.XMM0);
XS.SSE.MoveSS(XSRegisters.ESP, XSRegisters.XMM2, destinationIsIndirect: true);
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
XS.SSE.XorPS(XMM2, XMM2);
XS.SSE.DivPS(XMM1, XMM0);
XS.SSE.MoveSS(ESP, XMM2, destinationIsIndirect: true);
}
else
{
@ -38,53 +39,53 @@ namespace Cosmos.IL2CPU.X86.IL
// divisor
//low
XS.Test(XSRegisters.ESI, XSRegisters.ESP, sourceIsIndirect: true);
XS.Test(ESI, ESP, sourceIsIndirect: true);
//high
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
// pop both 8 byte values
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 16);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 16);
//dividend
// low
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 8);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 8);
//high
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 12);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EDX), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 12);
// set flags
XS.Or(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI));
XS.Or(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.EDI));
// if high dword of divisor is already zero, we dont need the loop
XS.Jump(CPUx86.ConditionalTestEnum.Zero, LabelNoLoop);
// set ecx to zero for counting the shift operations
XS.Xor(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Xor(OldToNewRegister(CPUx86.RegistersEnum.ECX), OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Label(LabelShiftRight);
// shift divisor 1 bit right
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.RegistersEnum.ESI, SourceReg = CPUx86.RegistersEnum.EDI, ArgumentValue = 1 };
XS.ShiftRight(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), 1);
XS.ShiftRightDouble(ESI, EDI, 1);
XS.ShiftRight(OldToNewRegister(CPUx86.RegistersEnum.EDI), 1);
// increment shift counter
XS.Increment(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Increment(OldToNewRegister(CPUx86.RegistersEnum.ECX));
// set flags
XS.Or(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI));
XS.Or(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.EDI));
// loop while high dword of divisor till it is zero
XS.Jump(CPUx86.ConditionalTestEnum.NotZero, LabelShiftRight);
// shift the divident now in one step
// shift divident CL bits right
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.RegistersEnum.EAX, SourceReg = CPUx86.RegistersEnum.EDX, ArgumentReg = CPUx86.RegistersEnum.CL };
XS.ShiftRight(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.CL);
XS.ShiftRightDouble(EAX, EDX, CL);
XS.ShiftRight(OldToNewRegister(CPUx86.RegistersEnum.EDX), CL);
// so we shifted both, so we have near the same relation as original values
// divide this
XS.IntegerDivide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.IntegerDivide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// save result to stack
XS.Push(0);
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EDX));
//TODO: implement proper derivation correction and overflow detection
@ -92,18 +93,18 @@ namespace Cosmos.IL2CPU.X86.IL
XS.Label(LabelNoLoop);
//save high dividend
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.ECX), OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.EDX));
// extend that sign is in edx
XS.SignExtendAX(XSRegisters.RegisterSize.Int32);
XS.SignExtendAX(RegisterSize.Int32);
// divide high part
XS.IntegerDivide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.IntegerDivide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.ECX));
// divide low part
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// save low result
XS.Push(0);
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Label(LabelEnd);
}
@ -112,23 +113,23 @@ namespace Cosmos.IL2CPU.X86.IL
{
if (TypeIsFloat(xStackItem))
{
XS.SSE.MoveSS(XSRegisters.XMM0, XSRegisters.ESP, sourceIsIndirect: true);
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XSRegisters.XMM1, XSRegisters.ESP, sourceIsIndirect: true);
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.XorPS(XSRegisters.XMM2, XSRegisters.XMM2);
XS.SSE.DivSS(XSRegisters.XMM1, XSRegisters.XMM0);
XS.Sub(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XSRegisters.ESP, XSRegisters.XMM2, destinationIsIndirect: true);
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.XorPS(XMM2, XMM2);
XS.SSE.DivSS(XMM1, XMM0);
XS.Sub(OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(ESP, XMM2, destinationIsIndirect: true);
}
else
{
XS.Pop(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Pop(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX)); // gets devised by ecx
XS.Xor(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Pop(OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Pop(OldToNewRegister(CPUx86.RegistersEnum.EAX)); // gets devised by ecx
XS.Xor(OldToNewRegister(CPUx86.RegistersEnum.EDX), OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX)); // => EAX / ECX
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ECX)); // => EAX / ECX
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EDX));
}
}
}

View file

@ -1,6 +1,7 @@
using System;
using Cosmos.Assembler.x86.SSE;
using XSharp.Compiler;
using static XSharp.Compiler.XSRegisters;
using CPUx86 = Cosmos.Assembler.x86;
using Label = Cosmos.Assembler.Label;
@ -26,12 +27,12 @@ namespace Cosmos.IL2CPU.X86.IL
{
if (TypeIsFloat(xStackItem))
{
XS.SSE.MoveSS(XSRegisters.XMM0, XSRegisters.ESP, sourceIsIndirect: true);
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
XS.SSE.MoveSS(XSRegisters.XMM1, XSRegisters.ESP, sourceIsIndirect: true);
XS.SSE.XorPS(XSRegisters.XMM2, XSRegisters.XMM2);
XS.SSE.DivPS(XSRegisters.XMM1, XSRegisters.XMM0);
XS.SSE.MoveSS(XSRegisters.ESP, XSRegisters.XMM2, destinationIsIndirect: true);
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 8);
XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
XS.SSE.XorPS(XMM2, XMM2);
XS.SSE.DivPS(XMM1, XMM0);
XS.SSE.MoveSS(ESP, XMM2, destinationIsIndirect: true);
}
else
{
@ -42,53 +43,53 @@ namespace Cosmos.IL2CPU.X86.IL
// divisor
//low
XS.Set(XSRegisters.ESI, XSRegisters.ESP, sourceIsIndirect: true);
XS.Set(ESI, ESP, sourceIsIndirect: true);
//high
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 4);
//dividend
// low
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 8);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 8);
//high
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 12);
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EDX), OldToNewRegister(CPUx86.RegistersEnum.ESP), sourceDisplacement: 12);
// pop both 8 byte values
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 16);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 16);
// set flags
XS.Or(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI));
XS.Or(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.EDI));
// if high dword of divisor is already zero, we dont need the loop
XS.Jump(CPUx86.ConditionalTestEnum.Zero, LabelNoLoop);
// set ecx to zero for counting the shift operations
XS.Xor(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Xor(OldToNewRegister(CPUx86.RegistersEnum.ECX), OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Label(LabelShiftRight);
// shift divisor 1 bit right
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.RegistersEnum.ESI, SourceReg = CPUx86.RegistersEnum.EDI, ArgumentValue = 1 };
XS.ShiftRight(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), 1);
XS.ShiftRightDouble(ESI, EDI, 1);
XS.ShiftRight(OldToNewRegister(CPUx86.RegistersEnum.EDI), 1);
// increment shift counter
XS.Increment(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Increment(OldToNewRegister(CPUx86.RegistersEnum.ECX));
// set flags
XS.Or(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDI));
XS.Or(OldToNewRegister(CPUx86.RegistersEnum.EDI), OldToNewRegister(CPUx86.RegistersEnum.EDI));
// loop while high dword of divisor till it is zero
XS.Jump(CPUx86.ConditionalTestEnum.NotZero, LabelShiftRight);
// shift the divident now in one step
// shift divident CL bits right
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.RegistersEnum.EAX, SourceReg = CPUx86.RegistersEnum.EDX, ArgumentReg = CPUx86.RegistersEnum.CL };
XS.ShiftRight(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.CL);
XS.ShiftRightDouble(EAX, EDX, CL);
XS.ShiftRight(OldToNewRegister(CPUx86.RegistersEnum.EDX), CL);
// so we shifted both, so we have near the same relation as original values
// divide this
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// save remainder to stack
XS.Push(0);
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EDX));
//TODO: implement proper derivation correction and overflow detection
@ -97,18 +98,18 @@ namespace Cosmos.IL2CPU.X86.IL
XS.Label(LabelNoLoop);
//save high dividend
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.ECX), OldToNewRegister(CPUx86.RegistersEnum.EAX));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.EDX));
// zero EDX, so that high part is zero -> reduce overflow case
XS.Xor(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Xor(OldToNewRegister(CPUx86.RegistersEnum.EDX), OldToNewRegister(CPUx86.RegistersEnum.EDX));
// divide high part
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Set(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Set(OldToNewRegister(CPUx86.RegistersEnum.EAX), OldToNewRegister(CPUx86.RegistersEnum.ECX));
// divide low part
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESI));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ESI));
// save remainder result
XS.Push(0);
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Label(LabelEnd);
}
@ -117,23 +118,23 @@ namespace Cosmos.IL2CPU.X86.IL
{
if (TypeIsFloat(xStackItem))
{
XS.SSE.MoveSS(XSRegisters.XMM0, XSRegisters.ESP, sourceIsIndirect: true);
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XSRegisters.XMM1, XSRegisters.ESP, sourceIsIndirect: true);
XS.Add(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.XorPS(XSRegisters.XMM2, XSRegisters.XMM2);
XS.SSE.DivPS(XSRegisters.XMM1, XSRegisters.XMM0);
XS.Sub(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XSRegisters.ESP, XSRegisters.XMM2, destinationIsIndirect: true);
XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true);
XS.Add(OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.XorPS(XMM2, XMM2);
XS.SSE.DivPS(XMM1, XMM0);
XS.Sub(OldToNewRegister(CPUx86.RegistersEnum.ESP), 4);
XS.SSE.MoveSS(ESP, XMM2, destinationIsIndirect: true);
}
else
{
XS.Pop(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Pop(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EAX)); // gets devised by ecx
XS.Xor(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX), XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Pop(OldToNewRegister(CPUx86.RegistersEnum.ECX));
XS.Pop(OldToNewRegister(CPUx86.RegistersEnum.EAX)); // gets devised by ecx
XS.Xor(OldToNewRegister(CPUx86.RegistersEnum.EDX), OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Divide(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX)); // => EAX / ECX
XS.Push(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.EDX));
XS.Divide(OldToNewRegister(CPUx86.RegistersEnum.ECX)); // => EAX / ECX
XS.Push(OldToNewRegister(CPUx86.RegistersEnum.EDX));
}
}
}

View file

@ -2,6 +2,7 @@ using System;
using CPUx86 = Cosmos.Assembler.x86;
using Cosmos.Assembler;
using XSharp.Compiler;
using static XSharp.Compiler.XSRegisters;
namespace Cosmos.IL2CPU.X86.IL
{
@ -15,7 +16,7 @@ namespace Cosmos.IL2CPU.X86.IL
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode )
{
XS.Pop(XSRegisters.OldToNewRegister(CPUx86.RegistersEnum.ECX)); // shift amount
XS.Pop(OldToNewRegister(CPUx86.RegistersEnum.ECX)); // shift amount
var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0];
var xStackItem_Value = aOpCode.StackPopTypes[1];
var xStackItem_Value_Size = SizeOfType(xStackItem_Value);
@ -41,13 +42,14 @@ namespace Cosmos.IL2CPU.X86.IL
// [ESP + 4] is high part
// move low part to eax
XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceIsIndirect: true);
XS.Set(EAX, ESP, sourceIsIndirect: true);
new CPUx86.Compare { DestinationReg = CPUx86.RegistersEnum.CL, SourceValue = 32, Size = 8 };
XS.Jump(CPUx86.ConditionalTestEnum.AboveOrEqual, LowPartIsZero);
// shift higher part
new CPUx86.ShiftLeftDouble { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceReg = CPUx86.RegistersEnum.EAX, ArgumentReg = CPUx86.RegistersEnum.CL };
XS.ShiftLeftDouble(ESP, EAX, CL, destinationDisplacement: 4);
// shift lower part
new CPUx86.ShiftLeft { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, Size = 32, SourceReg = CPUx86.RegistersEnum.CL };
XS.Jump(End_Shl);
@ -57,7 +59,7 @@ namespace Cosmos.IL2CPU.X86.IL
new CPUx86.And { DestinationReg = CPUx86.RegistersEnum.CL, SourceValue = 0x1f, Size = 8 };
// shift low part in EAX and move it in high part
new CPUx86.ShiftLeft { DestinationReg = CPUx86.RegistersEnum.EAX, SourceReg = CPUx86.RegistersEnum.CL, Size = 32};
XS.Set(XSRegisters.ESP, XSRegisters.EAX, destinationDisplacement: 4);
XS.Set(ESP, EAX, destinationDisplacement: 4);
// replace unknown low part with a zero, if <= 32
new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, SourceValue = 0 };

View file

@ -49,7 +49,7 @@ namespace Cosmos.IL2CPU.X86.IL
XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero);
// shift lower part
new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.RegistersEnum.EAX, ArgumentReg = CPUx86.RegistersEnum.CL };
XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true);
// shift higher part
XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32);
XS.Jump(End_Shr);

View file

@ -1146,5 +1146,73 @@ namespace XSharp.Compiler
{
Do<RotateThroughCarryRight>(destination, source, destinationIsIndirect, destinationDisplacement, sourceIsIndirect, sourceDisplacement, size: size);
}
public static void ShiftRightDouble(Register destination, Register source, uint argumentValue)
{
new ShiftRightDouble()
{
DestinationReg = destination,
SourceReg = source,
ArgumentValue = argumentValue
};
}
public static void ShiftRightDouble(Register destination, Register source, Register8 argumentReg, bool destinationIsIndirect = false, int? destinationDisplacement = null)
{
if (argumentReg != CL)
{
throw new InvalidOperationException("Argument needs to be CL!");
}
if (destinationDisplacement != null)
{
destinationIsIndirect = true;
if (destinationDisplacement == 0)
{
destinationDisplacement = null;
}
}
new ShiftLeftDouble()
{
DestinationReg = destination,
DestinationIsIndirect = destinationIsIndirect,
DestinationDisplacement = destinationDisplacement,
SourceReg = source,
ArgumentReg = argumentReg
};
}
public static void ShiftLeftDouble(Register destination, Register source, uint argumentValue)
{
new ShiftRightDouble()
{
DestinationReg = destination,
SourceReg = source,
ArgumentValue = argumentValue
};
}
public static void ShiftLeftDouble(Register destination, Register source, Register8 argumentReg, bool destinationIsIndirect = false, int? destinationDisplacement = null)
{
if (argumentReg != CL)
{
throw new InvalidOperationException("Argument needs to be CL!");
}
if (destinationDisplacement != null)
{
destinationIsIndirect = true;
if (destinationDisplacement == 0)
{
destinationDisplacement = null;
}
}
new ShiftLeftDouble()
{
DestinationReg = destination,
DestinationIsIndirect = destinationIsIndirect,
DestinationDisplacement = destinationDisplacement,
SourceReg = source,
ArgumentReg = argumentReg
};
}
}
}