Example #1
0
 public CpuEmiter(MipsMethodEmiter MipsMethodEmiter, InstructionReader InstructionReader, Stream MemoryStream, CpuProcessor CpuProcessor)
 {
     this.MipsMethodEmiter = MipsMethodEmiter;
     this.InstructionReader = InstructionReader;
     this.MemoryStream = MemoryStream;
     this.CpuProcessor = CpuProcessor;
 }
Example #2
0
 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)
Example #6
0
 /// <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);
     }
 }
Example #8
0
        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);
        }
Example #9
0
        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;
            }
Example #11
0
        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);
        }
Example #14
0
        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();
            });
        }
Example #15
0
        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);
        }
Example #16
0
        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());
            }
        }
Example #17
0
        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());
            }
        }
Example #18
0
        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");
        }
Example #20
0
            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);
            }
Example #21
0
                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();
                    }
                }
Example #22
0
        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);
 }
Example #25
0
 public DynarecFunction CreateFunction(InstructionReader InstructionReader, uint PC)
 {
     var InternalFunctionCompiler = new InternalFunctionCompiler(this, InstructionReader, PC);
     return InternalFunctionCompiler.CreateFunction();
 }
                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();
                    }
                }
Example #27
0
        /// <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;
            }
        }
Example #28
0
        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);
        }
Example #29
0
 public override sealed void Initialize()
 {
     base.Initialize();
     m_CPUState = ParentMips.State;
     m_InstReader = new InstructionReader(MemoryAccessMode.Virtual);
     m_DataManipulator = new MipsDataManipulator(ParentMips.VirtualMemoryStream);
     InitializeOpcodes();
 }