Example #1
0
        private void compileDelaySlot(CompilerContext context, MethodVisitor mv, CodeInstruction delaySlotCodeInstruction)
        {
            if (delaySlotCodeInstruction == null)
            {
                Console.WriteLine(string.Format("Cannot find delay slot instruction at 0x{0:X8}", Address + 4));
                return;
            }

            if (delaySlotCodeInstruction.hasFlags(Instruction.FLAG_HAS_DELAY_SLOT))
            {
                // Issue a warning when compiling an instruction having a delay slot inside a delay slot.
                // See http://code.google.com/p/pcsx2/source/detail?r=5541
                string lineSeparator = System.getProperty("line.separator");
                Console.WriteLine(string.Format("Instruction in a delay slot having a delay slot:{0}{1}{2}{3}", lineSeparator, this, lineSeparator, delaySlotCodeInstruction));
            }

            delaySlotCodeInstruction.IsDelaySlot = true;
            Label delaySlotLabel = null;

            if (delaySlotCodeInstruction.hasLabel())
            {
                delaySlotLabel = delaySlotCodeInstruction.Label;
                delaySlotCodeInstruction.forceNewLabel();
            }
            delaySlotCodeInstruction.compile(context, mv);
            if (delaySlotLabel != null)
            {
                delaySlotCodeInstruction.Label = delaySlotLabel;
            }
            else if (delaySlotCodeInstruction.hasLabel())
            {
                delaySlotCodeInstruction.forceNewLabel();
            }
            context.CodeInstruction = this;
            context.skipInstructions(1, false);
        }
Example #2
0
        private int getBranchingOpcodeBranch2(CompilerContext context, MethodVisitor mv, int branchingOpcode, int notBranchingOpcode)
        {
            // Retrieve the registers for the branching opcode before executing
            // the delay slot instruction, as it might theoretically modify the
            // content of these registers.
            branchingOpcode = loadRegistersForBranchingOpcodeBranch2(context, mv, branchingOpcode);

            CodeInstruction delaySlotCodeInstruction = getDelaySlotCodeInstruction(context);

            if (delaySlotCodeInstruction != null && delaySlotCodeInstruction.hasFlags(Instruction.FLAG_HAS_DELAY_SLOT))
            {
                // We are compiling a sequence where the delay instruction has itself a delay slot:
                //    beq $reg1, $reg2, label
                //    jr  $ra
                //    nop
                // Handle the sequence by inserting one nop between the instructions:
                //    bne $reg1, $reg2, label
                //    nop
                //    jr  $ra
                //    nop
                string lineSeparator = System.getProperty("line.separator");
                Console.WriteLine(string.Format("Instruction in a delay slot having a delay slot:{0}{1}{2}{3}", lineSeparator, this, lineSeparator, delaySlotCodeInstruction));
            }
            else
            {
                compileDelaySlot(context, mv, delaySlotCodeInstruction);
            }

            if (branchingOpcode == Opcodes.GOTO && BranchingTo == Address && delaySlotCodeInstruction.Opcode == NOP())
            {
                context.visitLogInfo(mv, string.Format("Pausing emulator - branch to self (death loop) at 0x{0:X8}", Address));
                context.visitPauseEmuWithStatus(mv, Emulator.EMU_STATUS_JUMPSELF);
            }

            return(branchingOpcode);
        }
Example #3
0
        private void compileBranch(CompilerContext context, MethodVisitor mv)
        {
            // Perform any required checkSync() before executing the delay slot instruction,
            // so that the emulation can be paused in a consistent state
            // before the branch and its delay slot.
            context.startJump(BranchingTo);

            int branchingOpcode = getBranchingOpcode(context, mv);

            if (branchingOpcode != Opcodes.NOP)
            {
                CodeInstruction branchingToCodeInstruction = context.CodeBlock.getCodeInstruction(BranchingTo);

                // Fallback when branching to the 2nd instruction of a native code sequence whose
                // 1st instruction is the delay slot instruction.
                // In such a case, assume a branch to the native code sequence.
                if (branchingToCodeInstruction == null)
                {
                    CodeInstruction nativeCodeInstruction = context.getCodeInstruction(BranchingTo - 4);
                    if (nativeCodeInstruction != null && nativeCodeInstruction is NativeCodeInstruction)
                    {
                        NativeCodeSequence nativeCodeSequence = ((NativeCodeInstruction)nativeCodeInstruction).NativeCodeSequence;
                        if (getDelaySlotCodeInstruction(context).Opcode == nativeCodeSequence.FirstOpcode)
                        {
                            //if (log.DebugEnabled)
                            {
                                Console.WriteLine(string.Format("0x{0:X8}: branching to the 2nd instruction of a native code sequence, assuming the 1st instruction", Address));
                            }
                            branchingToCodeInstruction = nativeCodeInstruction;
                        }
                    }
                }

                if (branchingToCodeInstruction != null)
                {
                    // Some applications do have branches to delay slot instructions
                    // (probably from programmers that didn't know/care about delay slots).
                    //
                    // Handle a branch to a NOP in a delay slot: just skip the NOP and assume the branch
                    // is to the instruction following the NOP.
                    // E.g.:
                    //    0x00000000    b 0x00000014 -> branching to a NOP in a delay slot, assume a branch to 0x00000018
                    //    0x00000004    nop
                    //    ...
                    //    0x00000010    b 0x00000020
                    //    0x00000014    nop
                    //    0x00000018    something
                    //
                    if (branchingToCodeInstruction.Insn == Instructions.NOP)
                    {
                        CodeInstruction beforeBranchingToCodeInstruction = context.CodeBlock.getCodeInstruction(BranchingTo - 4);
                        if (beforeBranchingToCodeInstruction != null && beforeBranchingToCodeInstruction.hasFlags(Instruction.FLAG_HAS_DELAY_SLOT))
                        {
                            //if (log.DebugEnabled)
                            {
                                Console.WriteLine(string.Format("0x{0:X8}: branching to a NOP in a delay slot, correcting to the next instruction", Address));
                            }
                            branchingToCodeInstruction = context.CodeBlock.getCodeInstruction(BranchingTo + 4);
                        }
                    }
                    context.visitJump(branchingOpcode, branchingToCodeInstruction);
                }
                else
                {
                    context.visitJump(branchingOpcode, BranchingTo);
                }
            }
        }