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) }; } } } }