private TranslatedSub TranslateTier0(CpuThreadState state, MemoryManager memory, long position) { Block block = Decoder.DecodeBasicBlock(state, memory, position); Block[] graph = new Block[] { block }; string subName = GetSubroutineName(position); ILEmitterCtx context = new ILEmitterCtx(_cache, graph, block, subName); do { context.EmitOpCode(); }while (context.AdvanceOpCode()); TranslatedSub subroutine = context.GetSubroutine(); subroutine.SetType(TranslatedSubType.SubTier0); _cache.AddOrUpdate(position, subroutine, block.OpCodes.Count); OpCode64 lastOp = block.GetLastOp(); return(subroutine); }
public static void Blx(CpuThreadState state, MemoryManager memory, OpCode64 opCode, bool x) { A32OpCodeBImmAl op = (A32OpCodeBImmAl)opCode; if (IsConditionTrue(state, op.Cond)) { uint pc = GetPc(state); if (state.Thumb) { state.R14 = pc | 1; } else { state.R14 = pc - 4U; } if (x) { state.Thumb = !state.Thumb; } if (!state.Thumb) { pc &= ~3U; } BranchWritePc(state, pc + (uint)op.Imm); } }
private static BasicBlock[] EmitAndGetBlocks(ILEmitterCtx context, Block[] blocks) { for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) { Block block = blocks[blkIndex]; context.CurrBlock = block; context.MarkLabel(context.GetLabel((long)block.Address)); for (int opcIndex = 0; opcIndex < block.OpCodes.Count; opcIndex++) { OpCode64 opCode = block.OpCodes[opcIndex]; context.CurrOp = opCode; bool isLastOp = opcIndex == block.OpCodes.Count - 1; if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address) { context.EmitSynchronization(); } ILLabel lblPredicateSkip = null; if (opCode is OpCode32 op && op.Cond < Condition.Al) { lblPredicateSkip = new ILLabel(); context.EmitCondBranch(lblPredicateSkip, op.Cond.Invert()); } opCode.Emitter(context); if (lblPredicateSkip != null) { context.MarkLabel(lblPredicateSkip); context.ResetBlockStateForPredicatedOp(); // 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 && block.Next == null) { context.EmitStoreContext(); context.EmitLdc_I8(opCode.Position + opCode.OpCodeSizeInBytes); context.Emit(OpCodes.Ret); } } } } return(context.GetBlocks()); }
public void TryOptMarkCondWithoutCmp() { _optOpLastCompare = CurrOp; InstEmitAluHelper.EmitAluLoadOpers(this); Stloc(CmpOptTmp2Index, VarType.Int); Stloc(CmpOptTmp1Index, VarType.Int); }
public void TryOptMarkCondWithoutCmp() { _optOpLastCompare = CurrOp; InstEmitAluHelper.EmitDataLoadOpers(this); Stloc(Tmp4Index, IoType.Int); Stloc(Tmp3Index, IoType.Int); }
private void ExecuteSubroutineA32(CpuThreadState state, MemoryManager memory) { do { OpCode64 opCode = Decoder.DecodeOpCode(state, memory, state.R15); opCode.Interpreter(state, memory, opCode); }while (state.R15 != 0 && state.Running); }
public static void B(CpuThreadState state, MemoryManager memory, OpCode64 opCode) { A32OpCodeBImmAl op = (A32OpCodeBImmAl)opCode; if (IsConditionTrue(state, op.Cond)) { BranchWritePc(state, GetPc(state) + (uint)op.Imm); } }
public void EmitStflg(int index) { //Set this only if any of the NZCV flag bits were modified. //This is used to ensure that, when emiting a direct IL branch //instruction for compare + branch sequences, we're not expecting //to use comparison values from an old instruction, when in fact //the flags were already overwritten by another instruction further along. if (index >= (int)PState.VBit) { _optOpLastFlagSet = CurrOp; } Stloc(index, VarType.Flag); }
private void ResetBlockState() { _ilBlock = _visitedBlocks[_currBlock]; _ilBlocks.Add(_ilBlock); _ilBlock.Next = GetOrCreateILBlock(_currBlock.Next); _ilBlock.Branch = GetOrCreateILBlock(_currBlock.Branch); _opcIndex = -1; _optOpLastFlagSet = null; _optOpLastCompare = null; }
public bool AdvanceOpCode() { if (_opcIndex + 1 == CurrBlock.OpCodes.Count && _blkIndex + 1 == _graph.Length) { return(false); } while (++_opcIndex >= (CurrBlock?.OpCodes.Count ?? 0)) { _blkIndex++; _opcIndex = -1; _optOpLastFlagSet = null; _optOpLastCompare = null; _ilBlock = _emitter.GetIlBlock(_blkIndex); } return(true); }
public static void Und(ILEmitterCtx context) { OpCode64 op = context.CurrOp; context.EmitStoreState(); context.EmitLdarg(TranslatedSub.StateArgIdx); context.EmitLdc_I8(op.Position); context.EmitLdc_I4(op.RawOpCode); context.EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.OnUndefined)); if (context.CurrBlock.Next != null) { context.EmitLoadState(context.CurrBlock.Next); } else { context.EmitLdc_I8(op.Position + 4); context.Emit(OpCodes.Ret); } }
public void EmitStflg(int index) { _optOpLastFlagSet = CurrOp; Stloc(index, IoType.Flag); }
private void ResetBlockState() { _optOpLastFlagSet = null; _optOpLastCompare = null; }
public static bool IsThumb(OpCode64 op) { return(op is OpCodeT16); }
public static void Blx(CpuThreadState state, MemoryManager memory, OpCode64 opCode) { Blx(state, memory, opCode, true); }