private void EmitOpCode() { if (_currBlock == null) { return; } int opcIndex = _opcIndex; if (opcIndex == 0) { MarkLabel(GetLabel(_currBlock.Position)); } bool isLastOp = opcIndex == CurrBlock.OpCodes.Count - 1; if (isLastOp && CurrBlock.Branch != null && (ulong)CurrBlock.Branch.Position <= (ulong)CurrBlock.Position) { EmitSynchronization(); } //On AARCH32 mode, (almost) all instruction can be conditionally //executed, and the required condition is encoded on the opcode. //We handle that here, skipping the instruction if the condition //is not met. We can just ignore it when the condition is "Always", //because in this case the instruction is always going to be executed. //Condition "Never" is also ignored because this is a special encoding //used by some unconditional instructions. ILLabel lblSkip = null; if (CurrOp is OpCode32 op && op.Cond < Condition.Al) { lblSkip = new ILLabel(); EmitCondBranch(lblSkip, GetInverseCond(op.Cond)); } CurrOp.Emitter(this); if (lblSkip != null) { MarkLabel(lblSkip); //If this is the last op on the block, and there's no "next" block //after this one, then we have to return right now, with the address //of the next instruction to be executed (in the case that the condition //is false, and the branch was not taken, as all basic blocks should end with //some kind of branch). if (isLastOp && CurrBlock.Next == null) { EmitStoreState(); EmitLdc_I8(CurrOp.Position + CurrOp.OpCodeSizeInBytes); Emit(OpCodes.Ret); } } _ilBlock.Add(new ILBarrier()); }
public void EmitRor(int amount) { if (amount > 0) { Stloc(RorTmpIndex, VarType.Int); Ldloc(RorTmpIndex, VarType.Int); EmitLdc_I4(amount); Emit(OpCodes.Shr_Un); Ldloc(RorTmpIndex, VarType.Int); EmitLdc_I4(CurrOp.GetBitsCount() - amount); Emit(OpCodes.Shl); Emit(OpCodes.Or); } }