Cosmos/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Branch.cs
kudzu_cp 76b48915c3
2009-07-26 23:39:14 +00:00

64 lines
2.5 KiB
C#

using System;
using Indy.IL2CPU.Assembler;
using CPU = Indy.IL2CPU.Assembler.X86;
namespace Cosmos.IL2CPU.X86.IL
{
[Cosmos.IL2CPU.OpCode(ILOpCode.Code.Beq)]
[Cosmos.IL2CPU.OpCode(ILOpCode.Code.Bge)]
[Cosmos.IL2CPU.OpCode(ILOpCode.Code.Bgt)]
[Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ble)]
[Cosmos.IL2CPU.OpCode(ILOpCode.Code.Blt)]
public class Branch : ILOp {
public Branch(Cosmos.IL2CPU.Assembler aAsmblr) : base(aAsmblr) {
}
public override void Execute(uint aMethodUID, ILOpCode aOpCode) {
var xStackContent = OldAsmblr.StackContents.Pop();
OldAsmblr.StackContents.Pop();
if (xStackContent.Size > 8) {
throw new Exception("StackSize > 8 not supported");
}
CPU.ConditionalTestEnum xTestOp;
switch (aOpCode.OpCode) {
case ILOpCode.Code.Beq:
xTestOp = CPU.ConditionalTestEnum.Zero;
break;
case ILOpCode.Code.Bge:
xTestOp = CPU.ConditionalTestEnum.GreaterThanOrEqualTo;
break;
case ILOpCode.Code.Bgt:
xTestOp = CPU.ConditionalTestEnum.GreaterThan;
break;
case ILOpCode.Code.Ble:
xTestOp = CPU.ConditionalTestEnum.LessThanOrEqualTo;
break;
case ILOpCode.Code.Blt:
xTestOp = CPU.ConditionalTestEnum.LessThan;
break;
default:
throw new Exception("Unknown OpCode for conditional branch.");
break;
}
if (xStackContent.Size <= 4) {
new CPU.Pop { DestinationReg = CPU.Registers.EAX };
new CPU.Pop { DestinationReg = CPU.Registers.EBX };
new CPU.Compare { DestinationReg = CPU.Registers.EAX, SourceReg = CPU.Registers.EBX };
new CPU.ConditionalJump { Condition = xTestOp, DestinationLabel = AssemblerNasm.TmpBranchLabel(aMethodUID, aOpCode) };
} else {
new CPU.Pop { DestinationReg = CPU.Registers.EAX };
new CPU.Pop { DestinationReg = CPU.Registers.EBX };
new CPU.Pop { DestinationReg = CPU.Registers.ECX };
new CPU.Pop { DestinationReg = CPU.Registers.EDX };
new CPU.Xor { DestinationReg = CPU.Registers.EAX, SourceReg = CPU.Registers.ECX };
new CPU.ConditionalJump { Condition = xTestOp, DestinationLabel = AssemblerNasm.TmpBranchLabel(aMethodUID, aOpCode) };
new CPU.Xor { DestinationReg = CPU.Registers.EBX, SourceReg = CPU.Registers.EDX };
new CPU.ConditionalJump { Condition = xTestOp, DestinationLabel = AssemblerNasm.TmpBranchLabel(aMethodUID, aOpCode) };
}
}
}
}