public CpuEmiter(MipsMethodEmiter MipsMethodEmiter, InstructionReader InstructionReader, Stream MemoryStream, CpuProcessor CpuProcessor) { this.MipsMethodEmiter = MipsMethodEmiter; this.InstructionReader = InstructionReader; this.MemoryStream = MemoryStream; this.CpuProcessor = CpuProcessor; }
public InstructionContext(InstructionReader reader) { if (reader == null) throw new ArgumentNullException("reader"); Instruction = reader.CurrentInstruction; InstructionBlock = reader.CurrentInstructionBlock; InstructionSequence = reader.CurrentInstructionSequence; }
public static void RedirectBranchInstructions(this InstructionBlock block, InstructionReader reader, InstructionWriter writer, InstructionSequence branchTargetSequence, Predicate<Instruction> predicate) { if (block.HasChildrenBlocks) { for (InstructionBlock block1 = block.FirstChildBlock; block1 != null; block1 = block1.NextSiblingBlock) { if (!block1.HasExceptionHandlers) RedirectBranchInstructions(block1, reader, writer, branchTargetSequence, predicate); } } reader.JumpToInstructionBlock(block); if (block.HasInstructionSequences) { for (InstructionSequence sequence = block.FirstInstructionSequence; sequence != null; sequence = sequence.NextSiblingSequence) { bool commit = false; writer.AttachInstructionSequence(sequence); reader.EnterInstructionSequence(sequence); while (reader.ReadInstruction()) { var opCode = reader.CurrentInstruction.OpCodeNumber; var opCodeInfo = reader.CurrentInstruction.OpCodeInfo; if ((opCodeInfo.FlowControl == FlowControl.Branch || opCodeInfo.FlowControl == FlowControl.Cond_Branch) && (predicate == null || predicate(reader.CurrentInstruction))) { commit = true; writer.EmitBranchingInstruction(opCode, branchTargetSequence); } else { reader.CurrentInstruction.Write(writer); } } reader.LeaveInstructionSequence(); writer.DetachInstructionSequence(commit); } } reader.LeaveInstructionBlock(); }
public void FillInStaticConstructor(bool createTemporaryAssemblies, string[] preloadOrder, string resourcesHash, Checksums checksums) { var loaderMethod = info.StaticConstructorMethod; InstructionReader reader = loaderMethod.MethodBody.CreateInstructionReader(); reader.EnterInstructionBlock(loaderMethod.MethodBody.RootInstructionBlock); reader.EnterInstructionSequence(loaderMethod.MethodBody.RootInstructionBlock.LastInstructionSequence); while (reader.ReadInstruction()) { if (reader.CurrentInstruction.OpCodeNumber == OpCodeNumber.Ret) { break; } } Console.WriteLine(reader.CurrentInstruction); reader.CurrentInstructionSequence.SplitAroundReaderPosition(reader, out _, out _); var newSequence = reader.CurrentInstructionBlock.AddInstructionSequence(null, NodePosition.Before, reader.CurrentInstructionSequence); InstructionWriter writer = InstructionWriter.GetInstance(); writer.AttachInstructionSequence(newSequence); var orderedResources = preloadOrder .Join(this.manifest.Resources, p => p.ToLowerInvariant(), r => { var parts = r.Name.Split('.'); GetNameAndExt(parts, out var name, out _); return(name); }, (s, r) => r)
/// <summary> /// This void will read instruction file, prepare the dataset to process batch files /// </summary> private void readInstruction() { if (string.IsNullOrEmpty(instructionFile)) { return; } instructionReader = new InstructionReader(instructionFile); }
public void Run(string instructionsFile) { using (var fileReader = new StreamReader(instructionsFile)) { var instructions = new InstructionReader(fileReader, new TextInstructionFactory()); Run(instructions); } }
private ICentralProcessingUnit BuildCPU(IArithmeticLogicUnit alu, IMemoryManagementUnit mmu, ISystemBridge bridge) { IInstructionConfigurator configurator = new InstructionConfigurator(bridge); IInstructionParser parser = new InstructionParser(configurator); InstructionReader reader = new InstructionReader(mmu, alu.IP); ICentralProcessingUnit cpu = new CentralProcessingUnit(alu, parser, reader); return(cpu); }
static void Main() { var instructions = Input.Value.Split(';').Select(i => new Instruction(i)).ToList(); var jobs = new InstructionReader(instructions).AllJobs; var jobAssigner = new JobAssigner(jobs, 5); jobAssigner.Execute(); Console.WriteLine($"It took {jobAssigner.NumberOfTicks} ticks"); }
//const int MaxNumberOfInstructions = 128 * 1024; //const int MaxNumberOfInstructions = 60; internal InternalFunctionCompiler(DynarecFunctionCompiler DynarecFunctionCompiler, InstructionReader InstructionReader, uint EntryPC) { //this.DynamicMethod = new DynamicMethod(); //this.SafeILGenerator = new SafeILGenerator(); this.DynarecFunctionCompiler = DynarecFunctionCompiler; this.InstructionReader = InstructionReader; this.EntryPC = EntryPC; }
public static void Problem2() { var keypad = new DiamondKeypadBuilder().Build("5"); var finder = new BathroomCodeFinder(); var code = finder.Code(keypad, () => InstructionReader.FromFile("P2.txt")); Console.WriteLine("Code = {0}", code); }
public void When() { var mock = new Moq.Mock<ITextInstructionFactory>(); mock.Setup( m => m.CreateInstruction(It.IsAny<string>())) .Returns((string s) => new StubInstruction(s)); _stringReader = new StringReader(StreamText); Instructions = new InstructionReader(_stringReader, mock.Object); }
bool ProcessInstruction(InstructionReader reader) { var instruction = reader.CurrentInstruction; if (instruction.OpCodeNumber != OpCodeNumber.Call || !instruction.MethodOperand.GetMethodDefinition().Equals(_manyMethod)) { return(true); } ProcessImportMany(instruction); return(true); }
private void PopulateProfilerData() { if (profilerService.Profiler == null) { return; } Dispatch(() => { callTreeRoot = new List <ICall>() { profilerService.Profiler.RootCall }; routines = profilerService.Profiler.Routines; var reader = new InstructionReader(0, storyService.Story.Memory); var instructions = profilerService.Profiler.InstructionTimings.Select(timing => { reader.Address = timing.Item1; var i = reader.NextInstruction(); return(new { Instruction = i, Address = i.Address, OpcodeName = i.Opcode.Name, OperandCount = i.OperandCount, TimesExecuted = timing.Item2.Item1, TotalTime = timing.Item2.Item2 }); }); this.instructions = instructions.OrderByDescending(x => x.TotalTime).ToList(); var opcodes = from i in instructions group i by i.Instruction.Opcode.Name into g select new { Name = g.Key, TotalTime = g.Aggregate(TimeSpan.Zero, (r, t) => r + t.TotalTime), Count = g.Sum(x => x.TimesExecuted), AverageILSize = profilerService.Profiler.GetAverageOpcodeILSize(g.Key) }; this.opcodes = opcodes.OrderByDescending(x => x.TotalTime).ToList(); AllPropertiesChanged(); }); }
public IKeyword Parse(ActionScriptReader acr) { acr.ReadString(); // skip "code" string // While there's still instructions to be read, continue reading while (!acr.PeekString().Contains("returnvoid") && !acr.PeekString().Contains("returnvalue")) { string instr = acr.ReadString(); if (!string.IsNullOrEmpty(instr)) { Instructions.Add(InstructionReader.ParseInstruction(instr)); } } return(this); }
private void StoryService_StoryClosing(object sender, StoryClosingEventArgs e) { machine = null; reader = null; currentInstruction = null; hasStepped = false; ChangeState(DebuggerState.Unavailable); var handler = MachineDestroyed; if (handler != null) { handler(this, new MachineDestroyedEventArgs()); } }
private void StoryService_StoryOpened(object sender, StoryOpenedEventArgs e) { e.Story.RegisterInterpreter(new Interpreter()); machine = new InterpretedZMachine(e.Story); reader = new InstructionReader(machine.PC, e.Story.Memory); machine.SetRandomSeed(42); machine.Quit += Machine_Quit; ChangeState(DebuggerState.Stopped); var handler = MachineCreated; if (handler != null) { handler(this, new MachineCreatedEventArgs()); } }
private static Instruction[] ReadInstructions(int address, byte[] memory, InstructionCache cache) { var reader = new InstructionReader(address, memory, cache); var instructions = new List <Instruction>(); var lastKnownAddress = address; while (true) { var i = reader.NextInstruction(); instructions.Add(i); if ((i.Opcode.IsReturn || i.Opcode.IsQuit) && reader.Address > lastKnownAddress) { break; } else if (i.Opcode.IsJump) { var jumpOffset = (short)i.Operands[0].Value; var jumpAddress = reader.Address + jumpOffset - 2; if (jumpAddress > lastKnownAddress) { lastKnownAddress = jumpAddress; } if (reader.Address > lastKnownAddress) { break; } } else if (i.HasBranch && i.Branch.Kind == BranchKind.Address) { var branchAddress = reader.Address + i.Branch.Offset - 2; if (branchAddress > lastKnownAddress) { lastKnownAddress = branchAddress; } } } return(instructions.ToArray()); }
public void FirstInstruction() { var story = LoadStory(); var initialPC = Header.ReadInitialPC(story.Memory); var ireader = new InstructionReader(initialPC, story.Memory, null); var i = ireader.NextInstruction(); Assert.That(i, Is.Not.Null, "null check"); Assert.That(i.Address, Is.EqualTo(0xa31d), "address check"); Assert.That(i.Length, Is.EqualTo(3), "length check"); Assert.That(i.Opcode.Kind, Is.EqualTo(OpcodeKind.OneOp), "opcode kind check"); Assert.That(i.Opcode.Number, Is.EqualTo(0x0f), "opcode number check"); Assert.That(i.OperandCount, Is.EqualTo(1), "operand count check"); Assert.That(i.Operands[0].Kind, Is.EqualTo(OperandKind.LargeConstant), "operand kind check"); Assert.That(i.Operands[0].Value, Is.EqualTo(0x34ce), "operand value check"); Assert.That(i.HasStoreVariable, Is.False, "store variable check"); Assert.That(i.HasBranch, Is.False, "branch check"); Assert.That(i.HasZText, Is.False, "ztext check"); }
private void AdvanceInstructionPosition(LexemeStream lexemeStream, int instructionPointer) { StartPosition = SeekableInstructionReader.Position; StartInstructionPointer = instructionPointer; var lexemeIndex = instructionPointer & LocalIndexMask; var lexemePageIndex = instructionPointer >> PageIndexShift; EnsurePagesCapacity(lexemePageIndex + 1); for (var iPage = lexemeStream.HeadPage; iPage <= lexemePageIndex; iPage++) { InstructionReader.RentBuffers(PageSize, out var instructionsBuffer, out var operandsBuffer); var pageSource = lexemeStream.Pages[iPage]; var pageCopy = new InstructionPage(instructionsBuffer, operandsBuffer, pageSource.PageIndex, pageSource.PageLength); Array.Copy(pageSource.InstructionsBuffer, 0, pageCopy.InstructionsBuffer, 0, pageCopy.PageLength); Array.Copy(pageSource.OperandsBuffer, 0, pageCopy.OperandsBuffer, 0, pageCopy.PageLength); pageCopy.ReferenceCount = pageSource.ReferenceCount; Pages[pageCopy.PageIndex] = pageCopy; } var lexemePage = Pages[lexemePageIndex]; lexemePage.PageLength = lexemeIndex; for (var i = lexemeIndex; i < PageSize; i++) { lexemePage.OperandsBuffer[i] = int.MinValue; lexemePage.InstructionsBuffer[i] = default; } HeadPage = lexemeStream.HeadPage; PageCount = lexemePageIndex + 1; ReadOperand(ref instructionPointer); }
public void VisitInstruction(InstructionReader reader) { if (reader.CurrentInstruction.OpCodeNumber == OpCodeNumber.Throw) { var assets = ((OnThrowTransformation)instance.Transformation).assets; context.InstructionBlock.MethodBody.InitLocalVariables = true; var variable = reader.CurrentInstructionBlock.DefineLocalVariable(assets.Exception, ""); InstructionSequence before, after; reader.CurrentInstructionSequence.SplitAroundReaderPosition(reader, out before, out after); var sequence = reader.CurrentInstructionBlock.AddInstructionSequence(null, NodePosition.After, before); var writer = new InstructionWriter(); writer.AttachInstructionSequence(sequence); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, variable); instance.AspectWeaverInstance.AspectRuntimeInstanceField.EmitLoadField(writer, context.MethodMapping.CreateWriter()); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, variable); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, assets.OnThrow); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, variable); writer.DetachInstructionSequence(); } }
private static T BuildInstance <T>() { var basetype = typeof(T); var implType = module.DefineType(basetype.FullName + "$Impl", TypeAttributes.Class | TypeAttributes.Sealed, basetype); ILGenerator il; foreach (var refMethod in basetype.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (refMethod.DeclaringType != typeof(object) && refMethod.IsVirtual && !refMethod.IsFinal) { var implMethod = implType.DefineMethod( name: refMethod.Name, attributes: MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.HideBySig, callingConvention: refMethod.CallingConvention, returnType: refMethod.ReturnType, parameterTypes: refMethod.GetParameters().Select(p => p.ParameterType).ToArray()); var instructions = InstructionReader.Create(refMethod).ToList(); il = implMethod.GetILGenerator(); foreach (var i in instructions) { var method = i.Operand as MethodInfo; if (method != null && method.DeclaringType == typeof(MathOperations)) { var argtype = method.GetGenericArguments()[0]; if (!argtype.IsGenericParameter) { var x = Expression.Parameter(argtype); var expr1 = exprReplaces[method.Name](x, x); if (expr1.Method != null) { i.Operand = expr1.Method; } else { var expr2 = Expression.Call(typeof(MathOperationsImpl), method.Name, null, x, x); i.Operand = expr2.Method; } } } i.Prepare(il); } foreach (var i in instructions) { i.EmitOn(il); } implType.DefineMethodOverride(implMethod, refMethod); } } var ctor = implType.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes); il = ctor.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, implType.BaseType.GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Ret); var type = implType.CreateType(); return((T)Activator.CreateInstance(type)); }
public abstract void VisitInstruction(InstructionReader instructionReader);
public static void RedirectBranchInstructions(this InstructionBlock block, InstructionReader reader, InstructionWriter writer, InstructionSequence branchTargetSequence) { RedirectBranchInstructions(block, reader, writer, branchTargetSequence, null); }
public DynarecFunction CreateFunction(InstructionReader InstructionReader, uint PC) { var InternalFunctionCompiler = new InternalFunctionCompiler(this, InstructionReader, PC); return InternalFunctionCompiler.CreateFunction(); }
/// <summary> /// This function relocates all the instructions and pointers of the loading executable. /// </summary> /// <param name="Relocs"></param> protected void RelocateRelocs(IEnumerable <Elf.Reloc> Relocs) { var InstructionReader = new InstructionReader(ElfLoader.MemoryStream); /* * Func<uint, Action<ref Instruction>> UpdateInstruction = (Address) => * { * }; */ //var Hi16List = new List<uint>(); ushort HiValue = 0; var DeferredHi16 = new LinkedList <uint>(); // We'll use this to relocate R_MIPS_HI16 when we get a R_MIPS_LO16 foreach (var Reloc in Relocs) { //Console.WriteLine(Reloc.ToStringDefault()); //Console.WriteLine(" {0:X}", RelocatedAddress); // Check if R_TYPE is 0xFF (break code) and break the loop // immediately in order to avoid fetching non existent program headers. // Some games (e.g.: "Final Fantasy: Dissidia") use this kind of relocation // suggesting that the PSP's ELF Loader is capable of recognizing it and stop. if (Reloc.Type == Elf.Reloc.TypeEnum.StopRelocation) { break; } var PointerBaseOffset = (uint)ElfLoader.ProgramHeaders[Reloc.PointerSectionHeaderBase].VirtualAddress; var PointeeBaseOffset = (uint)ElfLoader.ProgramHeaders[Reloc.PointeeSectionHeaderBase].VirtualAddress; // Address of data to relocate var RelocatedPointerAddress = (uint)(BaseAddress + Reloc.PointerAddress + PointerBaseOffset); // Value of data to relocate var Instruction = InstructionReader[RelocatedPointerAddress]; var S = (uint)BaseAddress + PointeeBaseOffset; var GP_ADDR = (int)(BaseAddress + Reloc.PointerAddress); var GP_OFFSET = (int)GP_ADDR - ((int)BaseAddress & 0xFFFF0000); //Console.WriteLine(Reloc.Type); switch (Reloc.Type) { // Tested on PSP: R_MIPS_NONE just returns 0. case Elf.Reloc.TypeEnum.None: // 0 { } break; /* * case Elf.Reloc.TypeEnum.Mips16: // 1 * { * Instruction.IMMU += S; * } * break; */ case Elf.Reloc.TypeEnum.Mips32: // 2 { Instruction.Value += S; } break; case Elf.Reloc.TypeEnum.MipsRel32: // 3; { throw (new NotImplementedException()); } case Elf.Reloc.TypeEnum.Mips26: // 4 { Instruction.JUMP_Real = Instruction.JUMP_Real + S; } break; case Elf.Reloc.TypeEnum.MipsHi16: // 5 { HiValue = (ushort)Instruction.IMMU; DeferredHi16.AddLast(RelocatedPointerAddress); } break; case Elf.Reloc.TypeEnum.MipsLo16: // 6 { uint A = Instruction.IMMU; Instruction.IMMU = ((uint)(HiValue << 16) | (uint)(A & 0x0000FFFF)) + S; // Process deferred R_MIPS_HI16 foreach (var data_addr2 in DeferredHi16) { var data2 = InstructionReader[data_addr2]; uint result = ((data2.Value & 0x0000FFFF) << 16) + A + S; // The low order 16 bits are always treated as a signed // value. Therefore, a negative value in the low order bits // requires an adjustment in the high order bits. We need // to make this adjustment in two ways: once for the bits we // took from the data, and once for the bits we are putting // back in to the data. if ((A & 0x8000) != 0) { result -= 0x10000; } if ((result & 0x8000) != 0) { result += 0x10000; } data2.IMMU = (result >> 16); InstructionReader[data_addr2] = data2; } DeferredHi16.Clear(); } break; case Elf.Reloc.TypeEnum.MipsGpRel16: // 7 { /* * int A = Instruction.IMM; * int result; * if (A == 0) * { * result = (int)S - (int)GP_ADDR; * } * else * { * result = (int)S + (int)GP_OFFSET + (int)(((A & 0x00008000) != 0) ? (((A & 0x00003FFF) + 0x4000) | 0xFFFF0000) : A) - (int)GP_ADDR; * } * if ((result < -32768) || (result > 32768)) * { * Console.Error.WriteLine("Relocation overflow (R_MIPS_GPREL16) : '" + result + "'"); * } * Instruction.IMMU = (uint)result; */ } break; default: throw(new NotImplementedException("Handling " + Reloc.Type + " not implemented")); } InstructionReader[RelocatedPointerAddress] = Instruction; } }
static private Action <CpuThreadState> _CreateDelegateForPC(CpuProcessor CpuProcessor, Stream MemoryStream, uint EntryPC, out int InstructionsProcessed) { InstructionsProcessed = 0; if (EntryPC == 0) { if (MemoryStream is PspMemoryStream) { throw (new InvalidOperationException("EntryPC can't be NULL")); } } if (CpuProcessor.PspConfig.TraceJIT) { Console.WriteLine("Emiting EntryPC=0x{0:X}", EntryPC); } MemoryStream.Position = EntryPC; if ((MemoryStream.Length >= 8) && new BinaryReader(MemoryStream).ReadUInt64() == 0x0000000003E00008) { Console.WriteLine("NullSub detected at 0x{0:X}!", EntryPC); } var InstructionReader = new InstructionReader(MemoryStream); var MipsMethodEmiter = new MipsMethodEmiter(MipsEmiter, CpuProcessor); var ILGenerator = MipsMethodEmiter.ILGenerator; var CpuEmiter = new CpuEmiter(MipsMethodEmiter, InstructionReader, MemoryStream, CpuProcessor); uint PC; uint EndPC = (uint)MemoryStream.Length; uint MinPC = uint.MaxValue, MaxPC = uint.MinValue; var Labels = new SortedDictionary <uint, Label>(); var BranchesToAnalyze = new Queue <uint>(); var AnalyzedPC = new HashSet <uint>(); Labels[EntryPC] = ILGenerator.DefineLabel(); BranchesToAnalyze.Enqueue(EntryPC); // PASS1: Analyze and find labels. PC = EntryPC; //Debug.WriteLine("PASS1: (PC={0:X}, EndPC={1:X})", PC, EndPC); var GlobalInstructionStats = CpuProcessor.GlobalInstructionStats; var InstructionStats = new Dictionary <string, uint>(); var NewInstruction = new Dictionary <string, bool>(); int MaxNumberOfInstructions = 8 * 1024; //int MaxNumberOfInstructions = 60; while (BranchesToAnalyze.Count > 0) { bool EndOfBranchFound = false; for (PC = BranchesToAnalyze.Dequeue(); PC < EndPC; PC += 4) { // If already analyzed, stop scanning this branch. if (AnalyzedPC.Contains(PC)) { break; } AnalyzedPC.Add(PC); //Console.WriteLine("%08X".Sprintf(PC)); if (AnalyzedPC.Count > MaxNumberOfInstructions) { throw (new InvalidDataException("Code sequence too long: >= " + MaxNumberOfInstructions + "")); } MinPC = Math.Min(MinPC, PC); MaxPC = Math.Max(MaxPC, PC); //Console.WriteLine(" PC:{0:X}", PC); CpuEmiter.LoadAT(PC); var BranchInfo = GetBranchInfo(CpuEmiter.Instruction.Value); if (CpuProcessor.PspConfig.LogInstructionStats) { var InstructionName = GetInstructionName(CpuEmiter.Instruction.Value, null); if (!InstructionStats.ContainsKey(InstructionName)) { InstructionStats[InstructionName] = 0; } InstructionStats[InstructionName]++; if (!GlobalInstructionStats.ContainsKey(InstructionName)) { NewInstruction[InstructionName] = true; GlobalInstructionStats[InstructionName] = 0; } GlobalInstructionStats[InstructionName]++; //var GlobalInstructionStats = CpuProcessor.GlobalInstructionStats; //var InstructionStats = new Dictionary<string, uint>(); //var NewInstruction = new Dictionary<string, bool>(); } // Branch instruction. if ((BranchInfo & CpuBranchAnalyzer.Flags.JumpInstruction) != 0) { //Console.WriteLine("Instruction"); EndOfBranchFound = true; continue; } else if ((BranchInfo & CpuBranchAnalyzer.Flags.BranchOrJumpInstruction) != 0) { var BranchAddress = CpuEmiter.Instruction.GetBranchAddress(PC); Labels[BranchAddress] = ILGenerator.DefineLabel(); BranchesToAnalyze.Enqueue(BranchAddress); // Jump Always performed. /* * if ((BranchInfo & CpuBranchAnalyzer.Flags.JumpAlways) != 0) * { * EndOfBranchFound = true; * continue; * } */ } else if ((BranchInfo & CpuBranchAnalyzer.Flags.SyscallInstruction) != 0) { // On this special Syscall if (CpuEmiter.Instruction.CODE == FunctionGenerator.NativeCallSyscallCode) { //PC += 4; break; } } // A Jump Always found. And we have also processed the delayed branch slot. End the branch. if (EndOfBranchFound) { EndOfBranchFound = false; break; } } } // PASS2: Generate code and put labels; Action <uint> _EmitCpuInstructionAT = (_PC) => { if (CpuProcessor.PspConfig.TraceJIT) { ILGenerator.Emit(OpCodes.Ldarg_0); ILGenerator.Emit(OpCodes.Ldc_I4, _PC); ILGenerator.Emit(OpCodes.Call, typeof(CpuThreadState).GetMethod("Trace")); Console.WriteLine(" PC=0x{0:X}", _PC); } CpuEmiter.LoadAT(_PC); CpuEmiterInstruction(CpuEmiter.Instruction.Value, CpuEmiter); }; uint InstructionsEmitedSinceLastWaypoint = 0; Action StorePC = () => { MipsMethodEmiter.SavePC(PC); }; Action <bool> EmitInstructionCountIncrement = (bool CheckForYield) => { if (!CpuProcessor.PspConfig.CountInstructionsAndYield) { return; } //Console.WriteLine("EmiteInstructionCountIncrement: {0},{1}", InstructionsEmitedSinceLastWaypoint, CheckForYield); if (InstructionsEmitedSinceLastWaypoint > 0) { MipsMethodEmiter.SaveStepInstructionCount(() => { MipsMethodEmiter.LoadStepInstructionCount(); ILGenerator.Emit(OpCodes.Ldc_I4, InstructionsEmitedSinceLastWaypoint); //ILGenerator.Emit(OpCodes.Add); ILGenerator.Emit(OpCodes.Sub); }); //ILGenerator.Emit(OpCodes.Ldc_I4, 100); //ILGenerator.EmitCall(OpCodes.Call, typeof(Console).GetMethod("WriteLine"), new Type[] { typeof(int) }); InstructionsEmitedSinceLastWaypoint = 0; } if (CheckForYield) { if (!CpuProcessor.PspConfig.BreakInstructionThreadSwitchingForSpeed) { var NoYieldLabel = ILGenerator.DefineLabel(); MipsMethodEmiter.LoadStepInstructionCount(); ILGenerator.Emit(OpCodes.Ldc_I4_0); ILGenerator.Emit(OpCodes.Bgt, NoYieldLabel); //ILGenerator.Emit(OpCodes.Ldc_I4, 1000000); //ILGenerator.Emit(OpCodes.Blt, NoYieldLabel); MipsMethodEmiter.SaveStepInstructionCount(() => { ILGenerator.Emit(OpCodes.Ldc_I4_0); }); StorePC(); ILGenerator.Emit(OpCodes.Ldarg_0); ILGenerator.Emit(OpCodes.Call, typeof(CpuThreadState).GetMethod("Yield")); //ILGenerator.Emit(OpCodes.Call, typeof(GreenThread).GetMethod("Yield")); ILGenerator.MarkLabel(NoYieldLabel); } } }; Action EmitCpuInstruction = () => { if (CpuProcessor.NativeBreakpoints.Contains(PC)) { ILGenerator.Emit(OpCodes.Call, typeof(DebugUtils).GetMethod("IsDebuggerPresentDebugBreak")); } // Marks label. if (Labels.ContainsKey(PC)) { EmitInstructionCountIncrement(false); ILGenerator.MarkLabel(Labels[PC]); } _EmitCpuInstructionAT(PC); PC += 4; InstructionsEmitedSinceLastWaypoint++; }; //Debug.WriteLine("PASS2: MinPC:{0:X}, MaxPC:{1:X}", MinPC, MaxPC); // Jumps to the entry point. ILGenerator.Emit(OpCodes.Br, Labels[EntryPC]); for (PC = MinPC; PC <= MaxPC;) { uint CurrentInstructionPC = PC; Instruction CurrentInstruction = InstructionReader[PC]; InstructionsProcessed++; /* * if (!AnalyzedPC.Contains(CurrentInstructionPC)) * { * // Marks label. * if (Labels.ContainsKey(PC)) * { * ILGenerator.MarkLabel(Labels[PC]); * } * * * PC += 4; * continue; * } */ var BranchInfo = GetBranchInfo(CurrentInstruction.Value); // Delayed branch instruction. if ((BranchInfo & CpuBranchAnalyzer.Flags.BranchOrJumpInstruction) != 0) { InstructionsEmitedSinceLastWaypoint += 2; EmitInstructionCountIncrement(true); var BranchAddress = CurrentInstruction.GetBranchAddress(PC); if ((BranchInfo & CpuBranchAnalyzer.Flags.JumpInstruction) != 0) { // Marks label. if (Labels.ContainsKey(PC)) { ILGenerator.MarkLabel(Labels[PC]); } _EmitCpuInstructionAT(PC + 4); _EmitCpuInstructionAT(PC + 0); PC += 8; } else { // Branch instruction. EmitCpuInstruction(); //if ((BranchInfo & CpuBranchAnalyzer.Flags.Likely) != 0) if (BranchInfo.HasFlag(CpuBranchAnalyzer.Flags.Likely)) { //Console.WriteLine("Likely"); // Delayed instruction. CpuEmiter._branch_likely(() => { EmitCpuInstruction(); }); } else { //Console.WriteLine("Not Likely"); // Delayed instruction. EmitCpuInstruction(); } if (CurrentInstructionPC + 4 != BranchAddress) { if (Labels.ContainsKey(BranchAddress)) { CpuEmiter._branch_post(Labels[BranchAddress]); } // Code not reached. else { } } } } // Normal instruction. else { // Syscall instruction. if ((BranchInfo & CpuBranchAnalyzer.Flags.SyscallInstruction) != 0) { StorePC(); } EmitCpuInstruction(); if ((BranchInfo & CpuBranchAnalyzer.Flags.SyscallInstruction) != 0) { // On this special Syscall if (CurrentInstruction.CODE == FunctionGenerator.NativeCallSyscallCode) { //PC += 4; break; } } } } if (CpuProcessor.PspConfig.ShowInstructionStats) { Console.Error.WriteLine("-------------------------- {0:X}-{1:X} ", MinPC, MaxPC); foreach (var Pair in InstructionStats.OrderByDescending(Item => Item.Value)) { Console.Error.Write("{0} : {1}", Pair.Key, Pair.Value); if (NewInstruction.ContainsKey(Pair.Key)) { Console.Error.Write(" <-- NEW!"); } Console.Error.WriteLine(""); } } //if (BreakPoint) IsDebuggerPresentDebugBreak(); Action <CpuThreadState> Delegate = MipsMethodEmiter.CreateDelegate(); return(Delegate); }
public override sealed void Initialize() { base.Initialize(); m_CPUState = ParentMips.State; m_InstReader = new InstructionReader(MemoryAccessMode.Virtual); m_DataManipulator = new MipsDataManipulator(ParentMips.VirtualMemoryStream); InitializeOpcodes(); }