Cosmos/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldarg.cs
Trivalik_cp 51e893eb74 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
2011-09-02 21:03:14 +00:00

126 lines
No EOL
4.7 KiB
C#

using System;
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
{
[Cosmos.IL2CPU.OpCode( ILOpCode.Code.Ldarg )]
public class Ldarg : ILOp
{
public Ldarg( Cosmos.Compiler.Assembler.Assembler aAsmblr )
: base( aAsmblr )
{
}
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode )
{
var xOpVar = (OpVar)aOpCode;
DoExecute(Assembler, aMethod, xOpVar.Value);
}
public static int GetArgumentDisplacement(MethodInfo aMethod, ushort aParam) {
var xMethodBase = aMethod.MethodBase;
if (aMethod.PluggedMethod != null) {
xMethodBase = aMethod.PluggedMethod.MethodBase;
}
var xMethodInfo = xMethodBase as System.Reflection.MethodInfo;
uint xReturnSize = 0;
if (xMethodInfo != null) {
xReturnSize = Align(SizeOfType(xMethodInfo.ReturnType), 4);
}
uint xOffset = 8;
var xCorrectedOpValValue = aParam;
if (!aMethod.MethodBase.IsStatic && aParam > 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 = xMethodBase.GetParameters();
if (aParam == 0 && !xMethodBase.IsStatic) {
// return the this parameter, which is not in .GetParameters()
uint xCurArgSize;
if (xMethodBase.DeclaringType.IsValueType)
{
// value types get a reference passed to the actual value, so pointer:
xCurArgSize = 4;
}
else
{
xCurArgSize = Align(SizeOfType(xMethodBase.DeclaringType), 4);
}
for (int i = xParams.Length - 1; i >= aParam; i--) {
var xSize = Align(SizeOfType(xParams[i].ParameterType), 4);
xOffset += xSize;
}
if (xReturnSize > xCurArgSize) {
uint xExtraSize = xReturnSize - xCurArgSize;
xOffset += xExtraSize;
}
return (int)(xOffset + xCurArgSize - 4);
} else {
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;
if (xReturnSize > xArgSize) {
uint xExtraSize = xReturnSize - xArgSize;
xOffset += xExtraSize;
}
return (int)(xOffset + xCurArgSize - 4);
}
}
public static void DoExecute(Assembler Assembler, MethodInfo aMethod, ushort aParam) {
var xDisplacement = GetArgumentDisplacement(aMethod, aParam);
Type xArgType;
if (aMethod.MethodBase.IsStatic) {
xArgType = aMethod.MethodBase.GetParameters()[aParam].ParameterType;
} else {
if (aParam == 0u) {
xArgType = aMethod.MethodBase.DeclaringType;
if (xArgType.IsValueType)
{
xArgType = xArgType.MakeByRefType();
}
} else {
xArgType = aMethod.MethodBase.GetParameters()[aParam - 1].ParameterType;
}
}
new Comment("Ldarg");
new Comment("Arg idx = " + aParam);
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);
}
}
}