/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { SigType I4 = new SigType(CilElementType.I4); RegisterOperand esp = new RegisterOperand(I4, GeneralPurposeRegister.ESP); context.SetInstruction(CPUx86.Instruction.MovInstruction, esp, context.Operand1); context.AppendInstruction(CPUx86.Instruction.PopadInstruction); context.AppendInstruction(CPUx86.Instruction.AddInstruction, esp, new ConstantOperand(I4, 0x08)); context.AppendInstruction(CPUx86.Instruction.StiInstruction); context.AppendInstruction(CPUx86.Instruction.IRetdInstruction); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { Operand result = context.Result; SigType u4 = new SigType(CilElementType.U4); RegisterOperand eax = new RegisterOperand(u4, GeneralPurposeRegister.EAX); context.SetInstruction(CPUx86.Instruction.PopInstruction, eax); context.AppendInstruction(CPUx86.Instruction.AddInstruction, eax, new RegisterOperand(u4, GeneralPurposeRegister.ESP)); context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(0))); context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, eax); context.AppendInstruction(CPUx86.Instruction.PushInstruction, null, eax); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { Operand result = context.Result; Operand operand1 = context.Operand1; RegisterOperand edx = new RegisterOperand(operand1.Type, GeneralPurposeRegister.EDX); RegisterOperand eax = new RegisterOperand(result.Type, GeneralPurposeRegister.EAX); context.SetInstruction(CPUx86.Instruction.MovInstruction, edx, operand1); context.AppendInstruction(CPUx86.Instruction.InInstruction, eax, edx); context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, eax); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> public void ReplaceIntrinsicCall(Context context) { Operand operand1 = context.Operand1; Operand operand2 = context.Operand2; RegisterOperand edx = new RegisterOperand (operand1.Type, GeneralPurposeRegister.EDX); RegisterOperand eax = new RegisterOperand (operand2.Type, GeneralPurposeRegister.EAX); context.SetInstruction (CPUx86.Instruction.MovInstruction, edx, operand1); context.AppendInstruction (CPUx86.Instruction.MovInstruction, eax, operand2); context.AppendInstruction (CPUx86.Instruction.OutInstruction, null, edx, eax); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> public void ReplaceIntrinsicCall(Context context) { Operand result = context.Result; Operand operand = context.Operand1; RegisterOperand eax = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), GeneralPurposeRegister.EAX); RegisterOperand ecx = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), GeneralPurposeRegister.ECX); RegisterOperand reg = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), GeneralPurposeRegister.EBX); context.SetInstruction(CPUx86.Instruction.MovInstruction, eax, operand); context.AppendInstruction(CPUx86.Instruction.XorInstruction, ecx, ecx); context.AppendInstruction(CPUx86.Instruction.CpuIdEbxInstruction); context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, reg); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { Operand dest = context.Operand1; Operand value = context.Operand2; RegisterOperand edx = new RegisterOperand(dest.Type, GeneralPurposeRegister.EDX); RegisterOperand eax = new RegisterOperand(value.Type, GeneralPurposeRegister.EAX); MemoryOperand memory = new MemoryOperand(new SigType(context.InvokeTarget.Signature.Parameters[1].Type), GeneralPurposeRegister.EDX, new IntPtr(0)); context.SetInstruction(CPUx86.Instruction.MovInstruction, edx, dest); context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, value); context.AppendInstruction(CPUx86.Instruction.MovInstruction, memory, eax); }
/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { // Create the prologue block Context ctx = new Context(InstructionSet, -1); // Add a jump instruction to the first block from the prologue ctx.AppendInstruction(IR.Instruction.JmpInstruction); //ctx.AppendInstruction(CIL.Instruction.Get(CIL.OpCode.Br)); ctx.SetBranch(0); ctx.Label = -1; _prologue = CreateBlock(-1, ctx.Index); SplitIntoBlocks(0); // Create the epilogue block ctx = new Context(InstructionSet, -1); // Add null instruction, necessary to generate a block index ctx.AppendInstruction(null); ctx.Ignore = true; ctx.Label = Int32.MaxValue; _epilogue = CreateBlock(Int32.MaxValue, ctx.Index); // Link all the blocks together BuildBlockLinks(_prologue); // Link Exception Header Clauses LinkExceptionHeaderClauses(); }
/// <summary> /// Initializes a new instance of the <see cref="TypeInitializerSchedulerStage"/> class. /// </summary> public TypeInitializerSchedulerStage() { InstructionSet = new InstructionSet(1024); _ctx = CreateContext(-1); _ctx.AppendInstruction(IR.Instruction.PrologueInstruction); _ctx.Other = 0; // stacksize }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.AddressOfInstruction"/> instruction. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.AddressOfInstruction(Context ctx) { Operand opRes = ctx.Result; RegisterOperand eax = new RegisterOperand (opRes.Type, GeneralPurposeRegister.EAX); ctx.Result = eax; ctx.ReplaceInstructionOnly (CPUx86.Instruction.LeaInstruction); // ctx.Ignore = true; ctx.AppendInstruction (CPUx86.Instruction.MovInstruction, opRes, eax); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> public void ReplaceIntrinsicCall(Context context) { Operand operand1 = context.Operand1; RegisterOperand imm = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EAX); context.SetInstruction(IR.Instruction.MoveInstruction, imm, operand1); context.AppendInstruction(IR.Instruction.MoveInstruction, new RegisterOperand(new SigType(CilElementType.U4), _control), imm); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { Operand result = context.Result; RegisterOperand imm = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EAX); context.SetInstruction(IR.Instruction.MoveInstruction, imm, new RegisterOperand(new SigType(CilElementType.U4), _control)); context.AppendInstruction(IR.Instruction.MoveInstruction, result, imm); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { Operand result = context.Result; RegisterOperand tmp = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EDX); MemoryOperand operand = new MemoryOperand(context.Operand1.Type, GeneralPurposeRegister.EDX, new System.IntPtr(0)); context.SetInstruction(CPUx86.Instruction.MovInstruction, tmp, context.Operand1); context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, operand); }
/// <summary> /// Create an empty block. /// </summary> /// <param name="label">The label.</param> /// <returns></returns> protected Context CreateEmptyBlockContext(int label) { Context ctx = new Context(InstructionSet, -1); BasicBlock block = CreateBlock(BasicBlocks.Count + 0x10000000); ctx.BasicBlock = block; // Need a dummy instruction at the start of each block to establish a starting point of the block ctx.AppendInstruction(null); ctx.Label = label; block.Index = ctx.Index; ctx.Ignore = true; return ctx; }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { MemoryOperand operand = new MemoryOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX, new System.IntPtr(0)); context.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.Ptr), GeneralPurposeRegister.EAX), context.Operand1); context.AppendInstruction(CPUx86.Instruction.LgdtInstruction, null, operand); RegisterOperand ax = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), GeneralPurposeRegister.EAX); RegisterOperand ds = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.DS); RegisterOperand es = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.ES); RegisterOperand fs = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.FS); RegisterOperand gs = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.GS); RegisterOperand ss = new RegisterOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I2), SegmentRegister.SS); context.AppendInstruction(CPUx86.Instruction.MovInstruction, ax, new ConstantOperand(new Mosa.Runtime.Metadata.Signatures.SigType(Mosa.Runtime.Metadata.CilElementType.I4), (int)0x00000010)); context.AppendInstruction(CPUx86.Instruction.MovInstruction, ds, ax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, es, ax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, fs, ax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, gs, ax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, ss, ax); context.AppendInstruction(CPUx86.Instruction.FarJmpInstruction); context.AppendInstruction(CPUx86.Instruction.NopInstruction); context.Previous.SetBranch(context.Offset); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { SigType u4 = new SigType(Runtime.Metadata.CilElementType.U4); // Retrieve register context context.SetInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(u4, GeneralPurposeRegister.EAX), new MemoryOperand(u4, GeneralPurposeRegister.ESP, new IntPtr(28))); // Restore registers (Note: EAX and EDX are NOT restored!) context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(u4, GeneralPurposeRegister.EDX), new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(28))); context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(u4, GeneralPurposeRegister.EBX), new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(4))); context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(u4, GeneralPurposeRegister.EDI), new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(20))); context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(u4, GeneralPurposeRegister.ESI), new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(16))); context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(u4, GeneralPurposeRegister.ESP), new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(32))); context.AppendInstruction(CPUx86.Instruction.MovInstruction, new RegisterOperand(u4, GeneralPurposeRegister.EBP), new MemoryOperand(u4, GeneralPurposeRegister.EAX, new IntPtr(24))); // Jmp to EIP (stored in EDX) context.AppendInstruction(CPUx86.Instruction.JmpInstruction); context.SetOperand(0, new RegisterOperand(u4, GeneralPurposeRegister.EDX)); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> public void ReplaceIntrinsicCall(Context context) { if (!(context.Operand1 is ConstantOperand)) throw new InvalidOperationException(); Operand result = context.Result; ControlRegister control; switch ((int)(context.Operand1 as ConstantOperand).Value) { case 0: control = ControlRegister.CR0; break; case 2: control = ControlRegister.CR2; break; case 3: control = ControlRegister.CR3; break; case 4: control = ControlRegister.CR4; break; default: throw new InvalidOperationException(); } RegisterOperand imm = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EAX); context.SetInstruction(IR.Instruction.MoveInstruction, imm, new RegisterOperand(new SigType(CilElementType.U4), control)); context.AppendInstruction(IR.Instruction.MoveInstruction, result, imm); }
private void HandleMemoryToMemoryOperation(Context ctx, Operand register, bool useStack) { Operand destination = ctx.Result; Operand source = ctx.Operand1; Debug.Assert(destination is MemoryOperand && source is MemoryOperand); if (register == null) register = new RegisterOperand(destination.Type, GeneralPurposeRegister.EDX); ctx.Operand1 = register; Context before = ctx.InsertBefore(); if (useStack) { before.SetInstruction(CPUx86.Instruction.PushInstruction, null, register); before.AppendInstruction(CPUx86.Instruction.MovInstruction, register, source); } else before.SetInstruction(CPUx86.Instruction.MovInstruction, register, source); if (useStack) ctx.AppendInstruction(CPUx86.Instruction.PopInstruction, register); }
/// <summary> /// Expands the neg instruction for 64-bits. /// </summary> /// <param name="context">The context.</param> private void ExpandXor(Context context) { Operand op0H, op1H, op2H, op0L, op1L, op2L; SplitLongOperand(context.Result, out op0L, out op0H); SplitLongOperand(context.Operand1, out op1L, out op1H); SplitLongOperand(context.Operand2, out op2L, out op2H); context.SetInstruction(CPUx86.Instruction.MovInstruction, op0H, op1H); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, op1L); context.AppendInstruction(CPUx86.Instruction.XorInstruction, op0H, op2H); context.AppendInstruction(CPUx86.Instruction.XorInstruction, op0L, op2L); }
/// <summary> /// Expands the unsigned move instruction for 64-bits. /// </summary> /// <param name="context">The context.</param> private void ExpandUnsignedMove(Context context) { MemoryOperand op0 = context.Result as MemoryOperand; Operand op1 = context.Operand1; Debug.Assert(op0 != null, @"I8 not in a memory operand!"); SigType U4 = new SigType(CilElementType.U4); Operand op0L, op0H, op1L, op1H; SplitLongOperand(op0, out op0L, out op0H); SplitLongOperand(op1, out op1L, out op1H); RegisterOperand eax = new RegisterOperand(U4, GeneralPurposeRegister.EAX); RegisterOperand edx = new RegisterOperand(U4, GeneralPurposeRegister.EDX); switch (op1.Type.Type) { case CilElementType.Boolean: context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, op0L, op1L); context.AppendInstruction(IR.Instruction.LogicalXorInstruction, op0H, op0H, op0H); break; case CilElementType.U1: context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, op1L); context.AppendInstruction(CPUx86.Instruction.CdqInstruction); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, eax); context.AppendInstruction(IR.Instruction.LogicalXorInstruction, op0H, op0H, op0H); break; case CilElementType.U2: goto case CilElementType.U1; case CilElementType.I4: context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, op1L); context.AppendInstruction(CPUx86.Instruction.XorInstruction, edx, edx); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, eax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx); break; case CilElementType.U4: context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, eax, op1L); context.AppendInstruction(CPUx86.Instruction.CdqInstruction); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, eax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx); break; case CilElementType.U8: context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, op0L, op1L); context.SetInstruction(IR.Instruction.ZeroExtendedMoveInstruction, op0H, op1H); break; case CilElementType.R4: throw new NotSupportedException(); case CilElementType.R8: throw new NotSupportedException(); default: throw new NotSupportedException(); } }
/// <summary> /// Expands the sub instruction for 64-bit operands. /// </summary> /// <param name="context">The context.</param> private void ExpandSub(Context context) { /* This function transforms the SUB into the following sequence of x86 instructions: * * mov eax, [op1] ; Move lower 32-bits of the first operand into eax * sub eax, [op2] ; Sub lower 32-bits of second operand to eax * mov [result], eax ; Save the result into the lower 32-bits of the result operand * mov eax, [op1+4] ; Move upper 32-bits of the first operand into eax * sbb eax, [op2+4] ; Sub with borrow upper 32-bits of the second operand to eax * mov [result+4], eax ; Save the result into the upper 32-bits of the result operand * */ // This only works for memory operands (can't store I8/U8 in a register.) // This fails for constant operands right now, which need to be extracted into memory // with a literal/literal operand first - TODO RegisterOperand eaxH = new RegisterOperand(new SigType(CilElementType.I4), GeneralPurposeRegister.EAX); RegisterOperand eaxL = new RegisterOperand(new SigType(CilElementType.U4), GeneralPurposeRegister.EAX); Operand op1L, op1H, op2L, op2H, resL, resH; SplitLongOperand(context.Operand1, out op1L, out op1H); SplitLongOperand(context.Operand2, out op2L, out op2H); SplitLongOperand(context.Result, out resL, out resH); context.SetInstruction(CPUx86.Instruction.MovInstruction, eaxL, op1L); context.AppendInstruction(CPUx86.Instruction.SubInstruction, eaxL, op2L); context.AppendInstruction(CPUx86.Instruction.MovInstruction, resL, eaxL); context.AppendInstruction(CPUx86.Instruction.MovInstruction, eaxH, op1H); context.AppendInstruction(CPUx86.Instruction.SbbInstruction, eaxH, op2H); context.AppendInstruction(CPUx86.Instruction.MovInstruction, resH, eaxH); }
/// <summary> /// Expands the store instruction for 64-bits. /// </summary> /// <param name="context">The context.</param> private void ExpandStore(Context context) { MemoryOperand op0 = context.Result as MemoryOperand; Operand offsetOperand = context.Operand1; MemoryOperand op2 = context.Operand2 as MemoryOperand; Debug.Assert(op0 != null && op2 != null, @"Operands to I8 LoadInstruction are not MemoryOperand."); SigType I4 = new SigType(CilElementType.I4); SigType U4 = new SigType(CilElementType.U4); Operand op1L, op1H; SplitLongOperand(op2, out op1L, out op1H); RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX); RegisterOperand edx = new RegisterOperand(I4, GeneralPurposeRegister.EDX); context.SetInstruction(CPUx86.Instruction.MovInstruction, edx, op0); // Fortunately in 32-bit mode, we can't have 64-bit offsets, so this plain add should suffice. context.AppendInstruction(CPUx86.Instruction.AddInstruction, edx, offsetOperand); context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1L); context.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(U4, GeneralPurposeRegister.EDX, IntPtr.Zero), eax); context.AppendInstruction(CPUx86.Instruction.MovInstruction, eax, op1H); context.AppendInstruction(CPUx86.Instruction.MovInstruction, new MemoryOperand(I4, GeneralPurposeRegister.EDX, new IntPtr(4)), eax); }
/// <summary> /// Expands the not instruction for 64-bits. /// </summary> /// <param name="context">The context.</param> private void ExpandNot(Context context) { Operand op0H, op1H, op0L, op1L; SplitLongOperand(context.Result, out op0L, out op0H); SplitLongOperand(context.Operand1, out op1L, out op1H); context.SetInstruction(IR.Instruction.LogicalNotInstruction, op0H, op1H); context.AppendInstruction(IR.Instruction.LogicalNotInstruction, op0L, op1L); }
/// <summary> /// Inserts the move instruction to load or spill an operand. /// </summary> /// <param name="ctx">The context.</param> /// <param name="destination">The destination operand.</param> /// <param name="source">The source operand.</param> private void InsertMove(Context ctx, Operand destination, Operand source) { //LegacyInstruction move = _architecture.CreateInstruction(typeof(IR.MoveInstruction), destination, source); //block.Instructions.Insert(idx, move); ctx.AppendInstruction(IR.Instruction.MoveInstruction, destination, source); }
/// <summary> /// Expands the binary comparison instruction for 64-bits. /// </summary> /// <param name="context">The context.</param> private void ExpandComparison(Context context) { Operand op0 = context.Result; Operand op1 = context.Operand1; Operand op2 = context.Operand2; Debug.Assert(op1 != null && op2 != null, @"IntegerCompareInstruction operand not memory!"); Debug.Assert(op0 is MemoryOperand || op0 is RegisterOperand, @"IntegerCompareInstruction result not memory and not register!"); SigType I4 = new SigType(CilElementType.I4); //UNUSED: //SigType U4 = new SigType(CilElementType.U4); Operand op1L, op1H, op2L, op2H; SplitLongOperand(op1, out op1L, out op1H); SplitLongOperand(op2, out op2L, out op2H); Context[] newBlocks = CreateEmptyBlockContexts(context.Label, 4); IR.ConditionCode conditionCode = context.ConditionCode; Context nextBlock = SplitContext(context, false); // Compare high dwords context.SetInstruction(CPUx86.Instruction.CmpInstruction, op1H, op2H); context.AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal, newBlocks[1].BasicBlock); context.AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[0].BasicBlock); LinkBlocks(context, newBlocks[0], newBlocks[1]); // Branch if check already gave results newBlocks[0].SetInstruction(CPUx86.Instruction.BranchInstruction, conditionCode, newBlocks[2].BasicBlock); newBlocks[0].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[3].BasicBlock); LinkBlocks(newBlocks[0], newBlocks[2], newBlocks[3]); // Compare low dwords newBlocks[1].SetInstruction(CPUx86.Instruction.CmpInstruction, op1L, op2L); // Set the unsigned result... newBlocks[1].AppendInstruction(CPUx86.Instruction.BranchInstruction, GetUnsignedConditionCode(conditionCode), newBlocks[2].BasicBlock); newBlocks[1].AppendInstruction(CPUx86.Instruction.JmpInstruction, newBlocks[3].BasicBlock); LinkBlocks(newBlocks[1], newBlocks[2], newBlocks[3]); // Success newBlocks[2].SetInstruction(CPUx86.Instruction.MovsxInstruction, op0, new ConstantOperand(I4, 1)); newBlocks[2].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock); LinkBlocks(newBlocks[2], nextBlock); // Failed newBlocks[3].SetInstruction(CPUx86.Instruction.MovsxInstruction, op0, new ConstantOperand(I4, 0)); newBlocks[3].AppendInstruction(CPUx86.Instruction.JmpInstruction, nextBlock.BasicBlock); LinkBlocks(newBlocks[3], nextBlock); }
/// <summary> /// Expands the and instruction for 64-bits. /// </summary> /// <param name="context">The context.</param> private void ExpandAnd(Context context) { Operand op0H, op1H, op2H, op0L, op1L, op2L; SplitLongOperand(context.Result, out op0L, out op0H); SplitLongOperand(context.Operand1, out op1L, out op1H); SplitLongOperand(context.Operand2, out op2L, out op2H); if (context.Result.StackType != StackTypeCode.Int64) { context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, op1L); context.AppendInstruction(CPUx86.Instruction.AndInstruction, op0L, op2L); } else { context.SetInstruction(CPUx86.Instruction.MovInstruction, op0H, op1H); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, op1L); context.AppendInstruction(CPUx86.Instruction.AndInstruction, op0H, op2H); context.AppendInstruction(CPUx86.Instruction.AndInstruction, op0L, op2L); } }
private void ProcessSingleTypeTruncation(Context ctx, IInstruction instruction, uint mask, Operand destinationOperand, Operand sourceOperand) { if (sourceOperand.Type.Type == CilElementType.I8 || sourceOperand.Type.Type == CilElementType.U8) { ctx.SetInstruction (IR.Instruction.MoveInstruction, destinationOperand, sourceOperand); ctx.AppendInstruction (instruction, destinationOperand, sourceOperand, new ConstantOperand (new SigType (CilElementType.U4), mask)); } else ctx.SetInstruction (instruction, destinationOperand, sourceOperand, new ConstantOperand (new SigType (CilElementType.U4), mask)); }
/// <summary> /// Creates the new temporary moves. /// </summary> /// <param name="ctx">The CTX.</param> /// <param name="block">The block.</param> /// <param name="stack">The stack.</param> private void CreateNewTemporaryMoves(Context ctx, BasicBlock block, Stack<Operand> stack) { Stack<Operand> nextStack = new Stack<Operand>(); foreach (Operand operand in stack) { Operand temp = MethodCompiler.CreateTemporary(operand.Type); nextStack.Push(temp); _operandStack.Pop(); ctx.AppendInstruction(IR.Instruction.MoveInstruction, temp, operand); } if (nextStack.Count > 0) foreach (BasicBlock nextBlock in block.NextBlocks) nextBlock.InitialStack = GetCurrentStack(nextStack); }
/// <summary> /// Links the temporary moves. /// </summary> /// <param name="ctx">The CTX.</param> /// <param name="block">The block.</param> /// <param name="nextBlock">The next block.</param> /// <param name="stack">The stack.</param> private void LinkTemporaryMoves(Context ctx, BasicBlock block, BasicBlock nextBlock, Stack<Operand> stack) { Stack<Operand> initialStack = GetCurrentStack(stack); Stack<Operand> nextInitialStack = GetCurrentStack(nextBlock.InitialStack); for (int i = 0; i < nextBlock.InitialStack.Count; ++i) ctx.AppendInstruction(IR.Instruction.MoveInstruction, nextInitialStack.Pop(), initialStack.Pop()); if (nextBlock.InitialStack.Count > 0) foreach (BasicBlock nBlock in block.NextBlocks) nBlock.InitialStack = GetCurrentStack(nextBlock.InitialStack); }
/// <summary> /// Expands the load instruction for 64-bits. /// </summary> /// <param name="context">The context.</param> private void ExpandLoad(Context context) { Operand op0 = context.Result; Operand op1 = context.Operand1; Operand offsetOperand = context.Operand2; Debug.Assert(op0 != null && op1 != null, @"Operands to I8 LoadInstruction are not MemoryOperand."); SigType I4 = new SigType(CilElementType.I4); Operand op0L, op0H; SplitLongOperand(op0, out op0L, out op0H); RegisterOperand eax = new RegisterOperand(I4, GeneralPurposeRegister.EAX); RegisterOperand edx = new RegisterOperand(I4, GeneralPurposeRegister.EDX); context.SetInstruction(CPUx86.Instruction.MovInstruction, eax, op1); context.AppendInstruction(CPUx86.Instruction.AddInstruction, eax, offsetOperand); context.AppendInstruction(CPUx86.Instruction.MovInstruction, edx, new MemoryOperand(op0L.Type, GeneralPurposeRegister.EAX, IntPtr.Zero)); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0L, edx); context.AppendInstruction(CPUx86.Instruction.MovInstruction, edx, new MemoryOperand(op0H.Type, GeneralPurposeRegister.EAX, new IntPtr(4))); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, edx); }
/// <summary> /// Expands the move instruction for 64-bits. /// </summary> /// <param name="context">The context.</param> private void ExpandMove(Context context) { Operand op0L, op0H, op1L, op1H; if (context.Result.StackType == StackTypeCode.Int64) { SplitLongOperand(context.Result, out op0L, out op0H); SplitLongOperand(context.Operand1, out op1L, out op1H); context.SetInstruction(CPUx86.Instruction.MovInstruction, op0L, op1L); context.AppendInstruction(CPUx86.Instruction.MovInstruction, op0H, op1H); } else { SplitLongOperand(context.Operand1, out op1L, out op1H); context.SetInstruction(CPUx86.Instruction.MovInstruction, context.Result, op1L); } }