Ejemplo n.º 1
0
void CDebugCommandsView::BeginOpEdit(uint32_t address)
{
    CRect listRect;
    m_CommandList.GetWindowRect(&listRect);
    ScreenToClient(&listRect);

    m_bEditing = true;
    //ShowAddress(address, FALSE);
    int nItem = (address - m_StartAddress) / 4;

    CRect itemRect;
    m_CommandList.GetSubItemRect(nItem, CCommandList::COL_COMMAND, 0, &itemRect);
    //itemRect.bottom += 0;
    itemRect.left += listRect.left + 3;
    itemRect.right += 100;

    uint32_t opcode;
    g_MMU->LW_VAddr(address, opcode);
    char* command = (char*)R4300iOpcodeName(opcode, address);

    m_OpEdit.ShowWindow(SW_SHOW);
    m_OpEdit.MoveWindow(&itemRect);
    m_OpEdit.BringWindowToTop();
    m_OpEdit.SetWindowTextA(command);
    m_OpEdit.SetFocus();
    m_OpEdit.SetSelAll();

    m_CommandList.RedrawWindow();
    m_OpEdit.RedrawWindow();
}
Ejemplo n.º 2
0
void CCPULog::DumpToFile(const char* path)
{
    FILE* fp = fopen(path, "wb");

    if (fp == NULL)
    {
        return;
    }

    size_t count = GetCount();

    for (size_t i = 0; i < count; i++)
    {
        CPUState* state = GetEntry(i);

        char *tokctx;

        char* szCommand = (char*)R4300iOpcodeName(state->opcode.Hex, state->pc);
        char* szCmdName = strtok_s((char*)szCommand, "\t", &tokctx);
        char* szCmdArgs = strtok_s(NULL, "\t", &tokctx);

        if (szCmdArgs == NULL)
        {
            szCmdArgs = "";
        }

        fprintf(fp, "%08X: %08X %s %s\n", state->pc, state->opcode.Hex, szCmdName, szCmdArgs);
    }

    fclose(fp);
}
Ejemplo n.º 3
0
void CDebugCommandsView::ShowAddress(uint32_t address, bool top)
{
    if (top == TRUE)
    {
        m_StartAddress = address;

        if (!isStepping())
        {
            // Disable buttons
            m_ViewPCButton.EnableWindow(FALSE);
            m_StepButton.EnableWindow(FALSE);
            m_StepOverButton.EnableWindow(FALSE);
            m_SkipButton.EnableWindow(FALSE);
            m_GoButton.EnableWindow(FALSE);

            m_RegisterTabs.SetColorsEnabled(false);
        }
    }
    else
    {
        bool bOutOfView = address < m_StartAddress ||
            address > m_StartAddress + (m_CommandListRows - 1) * 4;

        if (bOutOfView)
        {
            m_StartAddress = address;
            m_bIgnoreAddrChange = true;
            m_AddressEdit.SetValue(address, false, true);
        }

        if (m_History.size() == 0 || m_History[m_HistoryIndex] != m_StartAddress)
        {
            HistoryPushState();
        }

        m_bIgnorePCChange = true;
        m_PCEdit.SetValue(g_Reg->m_PROGRAM_COUNTER, false, true);

        // Enable buttons
        m_ViewPCButton.EnableWindow(TRUE);
        m_StepButton.EnableWindow(TRUE);
        m_StepOverButton.EnableWindow(TRUE);
        m_SkipButton.EnableWindow(TRUE);
        m_GoButton.EnableWindow(TRUE);

        m_RegisterTabs.SetColorsEnabled(true);
    }

    m_CommandList.SetRedraw(FALSE);
    m_CommandList.DeleteAllItems();

    ClearBranchArrows();

    m_bvAnnotatedLines.clear();

    CSymbols::EnterCriticalSection();

    for (int i = 0; i < m_CommandListRows; i++)
    {
        uint32_t opAddr = m_StartAddress + i * 4;

        m_CommandList.AddItem(i, CCommandList::COL_ARROWS, " ");

        char addrStr[9];
        sprintf(addrStr, "%08X", opAddr);

        m_CommandList.AddItem(i, CCommandList::COL_ADDRESS, addrStr);

        COpInfo OpInfo;
        OPCODE& OpCode = OpInfo.m_OpCode;
        bool bAddrOkay = false;

        if (AddressSafe(opAddr))
        {
            bAddrOkay = g_MMU->LW_VAddr(opAddr, OpCode.Hex);
        }

        if (!bAddrOkay)
        {
            m_CommandList.AddItem(i, CCommandList::COL_COMMAND, "***");
            m_bvAnnotatedLines.push_back(false);
            continue;
        }

        char* command = (char*)R4300iOpcodeName(OpCode.Hex, opAddr);
        char* cmdName = strtok((char*)command, "\t");
        char* cmdArgs = strtok(NULL, "\t");

        // Show subroutine symbol name for JAL target
        if (OpCode.op == R4300i_JAL)
        {
            uint32_t targetAddr = (0x80000000 | (OpCode.target << 2));

            // todo move symbols management to CDebuggerUI
            const char* targetSymbolName = CSymbols::GetNameByAddress(targetAddr);
            if (targetSymbolName != NULL)
            {
                cmdArgs = (char*)targetSymbolName;
            }
        }

        // Detect reads and writes to mapped registers, cart header data, etc
        const char* annotation = NULL;
        bool bLoadStoreAnnotation = false;

        if (OpInfo.IsLoadStoreCommand())
        {
            for (int offset = -4; offset > -24; offset -= 4)
            {
                if (!AddressSafe(opAddr + offset))
                {
                    break;
                }

                OPCODE OpCodeTest;
                bAddrOkay = g_MMU->LW_VAddr(opAddr + offset, OpCodeTest.Hex);

                if (!bAddrOkay)
                {
                    break;
                }

                if (OpCodeTest.op != R4300i_LUI)
                {
                    continue;
                }

                if (OpCodeTest.rt != OpCode.rs)
                {
                    continue;
                }

                uint32_t memAddr = (OpCodeTest.immediate << 16) + (short)OpCode.offset;

                annotation = CSymbols::GetNameByAddress(memAddr);

                if (annotation == NULL)
                {
                    annotation = GetDataAddressNotes(memAddr);
                }
                break;
            }
        }

        if (annotation == NULL)
        {
            annotation = GetCodeAddressNotes(opAddr);
        }
        else
        {
            bLoadStoreAnnotation = true;
        }

        m_CommandList.AddItem(i, CCommandList::COL_COMMAND, cmdName);
        m_CommandList.AddItem(i, CCommandList::COL_PARAMETERS, cmdArgs);

        // Show routine symbol name for this address
        const char* routineSymbolName = CSymbols::GetNameByAddress(opAddr);
        if (routineSymbolName != NULL)
        {
            m_CommandList.AddItem(i, CCommandList::COL_SYMBOL, routineSymbolName);
            m_bvAnnotatedLines.push_back(false);
        }
        else if (annotation != NULL)
        {
            const char* annotationFormat = bLoadStoreAnnotation ? "// (%s)" : "// %s";
            m_CommandList.AddItem(i, CCommandList::COL_SYMBOL, stdstr_f(annotationFormat, annotation).c_str());
            m_bvAnnotatedLines.push_back(true);
        }
        else
        {
            m_bvAnnotatedLines.push_back(false);
        }

        // Add arrow for branch instruction
        if (OpInfo.IsBranch())
        {
            int startPos = i;
            int endPos = startPos + (int16_t)OpCode.offset + 1;

            AddBranchArrow(startPos, endPos);
        }

        // Branch arrow for close J
        if (OpCode.op == R4300i_J)
        {
            uint32_t target = (OpCode.target << 2);
            int dist = target - (opAddr & 0x3FFFFFF);
            if (abs(dist) < 0x10000)
            {
                int startPos = i;
                int endPos = startPos + (dist / 4);
                AddBranchArrow(startPos, endPos);
            }
        }
    }

    CSymbols::LeaveCriticalSection();

    if (!top) // update registers when called via breakpoint/stepping
    {
        m_RegisterTabs.RefreshEdits();
    }

    RefreshBreakpointList();

    m_CommandList.SetRedraw(TRUE);
}
Ejemplo n.º 4
0
bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t & ContinuePC, bool & LikelyBranch, bool & IncludeDelaySlot, bool & EndBlock, bool & PermLoop)
{
    TargetPC = (uint32_t)-1;
    ContinuePC = (uint32_t)-1;
    LikelyBranch = false;
    IncludeDelaySlot = false;
    EndBlock = false;
    PermLoop = false;

    OPCODE Command;
    if (!g_MMU->LW_VAddr(PC, Command.Hex))
    {
        g_Notify->BreakPoint(__FILE__, __LINE__);
        return false;
    }

#ifdef _DEBUG
    const char * Name = R4300iOpcodeName(Command.Hex, PC);
    CPU_Message("  0x%08X %s", PC, Name);
#endif
    switch (Command.op)
    {
    case R4300i_SPECIAL:
        switch (Command.funct)
        {
        case R4300i_SPECIAL_SLL:    case R4300i_SPECIAL_SRL:    case R4300i_SPECIAL_SRA:
        case R4300i_SPECIAL_SLLV:   case R4300i_SPECIAL_SRLV:   case R4300i_SPECIAL_SRAV:
        case R4300i_SPECIAL_MFHI:   case R4300i_SPECIAL_MTHI:   case R4300i_SPECIAL_MFLO:
        case R4300i_SPECIAL_MTLO:   case R4300i_SPECIAL_DSLLV:  case R4300i_SPECIAL_DSRLV:
        case R4300i_SPECIAL_DSRAV:  case R4300i_SPECIAL_ADD:    case R4300i_SPECIAL_ADDU:
        case R4300i_SPECIAL_SUB:    case R4300i_SPECIAL_SUBU:   case R4300i_SPECIAL_AND:
        case R4300i_SPECIAL_OR:     case R4300i_SPECIAL_XOR:    case R4300i_SPECIAL_NOR:
        case R4300i_SPECIAL_SLT:    case R4300i_SPECIAL_SLTU:   case R4300i_SPECIAL_DADD:
        case R4300i_SPECIAL_DADDU:  case R4300i_SPECIAL_DSUB:   case R4300i_SPECIAL_DSUBU:
        case R4300i_SPECIAL_DSLL:   case R4300i_SPECIAL_DSRL:   case R4300i_SPECIAL_DSRA:
        case R4300i_SPECIAL_DSLL32: case R4300i_SPECIAL_DSRL32: case R4300i_SPECIAL_DSRA32:
        case R4300i_SPECIAL_MULT:   case R4300i_SPECIAL_MULTU:  case R4300i_SPECIAL_DIV:
        case R4300i_SPECIAL_DIVU:   case R4300i_SPECIAL_DMULT:  case R4300i_SPECIAL_DMULTU:
        case R4300i_SPECIAL_DDIV:   case R4300i_SPECIAL_DDIVU:
            break;
        case R4300i_SPECIAL_JALR:
        case R4300i_SPECIAL_JR:
            EndBlock = true;
            IncludeDelaySlot = true;
            break;
        case R4300i_SPECIAL_SYSCALL:
        case R4300i_SPECIAL_BREAK:
            EndBlock = true;
            break;
        default:
            g_Notify->BreakPoint(__FILE__, __LINE__);
            return false;
        }
        break;
    case R4300i_REGIMM:
        switch (Command.rt)
        {
        case R4300i_REGIMM_BLTZ:
        case R4300i_REGIMM_BLTZAL:
            TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
            if (TargetPC == PC + 8)
            {
                TargetPC = (uint32_t)-1;
            }
            else
            {
                if (TargetPC == PC && !DelaySlotEffectsCompare(PC, Command.rs, 0))
                {
                    PermLoop = true;
                }
                ContinuePC = PC + 8;
                IncludeDelaySlot = true;
            }
            break;
        case R4300i_REGIMM_BGEZ:
        case R4300i_REGIMM_BGEZAL:
            TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
            if (TargetPC == PC + 8)
            {
                TargetPC = (uint32_t)-1;
            }
            else
            {
                if (TargetPC == PC)
                {
                    if (Command.rs == 0)
                    {
                        TargetPC = (uint32_t)-1;
                        EndBlock = true;
                    }
                    else
                    {
                        if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
                        {
                            PermLoop = true;
                        }
                    }
                }
                if (Command.rs != 0)
                {
                    ContinuePC = PC + 8;
                }
                IncludeDelaySlot = true;
            }
            break;
        case R4300i_REGIMM_BLTZL:
        case R4300i_REGIMM_BGEZL:
            TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
            if (TargetPC == PC)
            {
                if (!DelaySlotEffectsCompare(PC, Command.rs, 0))
                {
                    PermLoop = true;
                }
            }
            ContinuePC = PC + 8;
            LikelyBranch = true;
            IncludeDelaySlot = true;
            break;
        default:
            if (Command.Hex == 0x0407000D)
            {
                EndBlock = true;
                break;
            }
            g_Notify->BreakPoint(__FILE__, __LINE__);
            return false;
        }
        break;
    case R4300i_J:
        TargetPC = (PC & 0xF0000000) + (Command.target << 2);
        if (TargetPC == PC)
        {
            PermLoop = true;
        }
        IncludeDelaySlot = true;
        break;
    case R4300i_JAL:
        EndBlock = true;
        IncludeDelaySlot = true;
        break;
    case R4300i_BEQ:
        TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
        if (TargetPC == PC + 8)
        {
            TargetPC = (uint32_t)-1;
        }
        else
        {
            if (Command.rs != 0 || Command.rt != 0)
            {
                ContinuePC = PC + 8;
            }

            if (TargetPC == PC && !DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
            {
                PermLoop = true;
            }
            IncludeDelaySlot = true;
        }
        break;
    case R4300i_BNE:
    case R4300i_BLEZ:
    case R4300i_BGTZ:
        TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
        if (TargetPC == PC + 8)
        {
            TargetPC = (uint32_t)-1;
        }
        else
        {
            if (TargetPC == PC)
            {
                if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
                {
                    PermLoop = true;
                }
            }
            ContinuePC = PC + 8;
            IncludeDelaySlot = true;
        }
        break;
    case R4300i_CP0:
        switch (Command.rs)
        {
        case R4300i_COP0_MT: case R4300i_COP0_MF:
            break;
        default:
            if ((Command.rs & 0x10) != 0)
            {
                switch (Command.funct)
                {
                case R4300i_COP0_CO_TLBR: case R4300i_COP0_CO_TLBWI:
                case R4300i_COP0_CO_TLBWR: case R4300i_COP0_CO_TLBP:
                    break;
                case R4300i_COP0_CO_ERET:
                    EndBlock = true;
                    break;
                default:
                    g_Notify->BreakPoint(__FILE__, __LINE__);
                    return false;
                }
            }
            else
            {
                g_Notify->BreakPoint(__FILE__, __LINE__);
                return false;
            }
            break;
        }
        break;
    case R4300i_CP1:
        switch (Command.fmt)
        {
        case R4300i_COP1_MF:  case R4300i_COP1_DMF: case R4300i_COP1_CF: case R4300i_COP1_MT:
        case R4300i_COP1_DMT: case R4300i_COP1_CT:  case R4300i_COP1_S:  case R4300i_COP1_D:
        case R4300i_COP1_W:   case R4300i_COP1_L:
            break;
        case R4300i_COP1_BC:
            switch (Command.ft) {
            case R4300i_COP1_BC_BCF:
            case R4300i_COP1_BC_BCT:
                TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
                if (TargetPC == PC + 8)
                {
                    TargetPC = (uint32_t)-1;
                }
                else
                {
                    if (TargetPC == PC)
                    {
                        g_Notify->BreakPoint(__FILE__, __LINE__);
                    }
                    ContinuePC = PC + 8;
                    IncludeDelaySlot = true;
                }
                break;
            case R4300i_COP1_BC_BCFL:
            case R4300i_COP1_BC_BCTL:
                TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
                if (TargetPC == PC)
                {
                    g_Notify->BreakPoint(__FILE__, __LINE__);
                }
                ContinuePC = PC + 8;
                LikelyBranch = true;
                IncludeDelaySlot = true;
                break;
            default:
                g_Notify->BreakPoint(__FILE__, __LINE__);
            }
            break;
        default:
            g_Notify->BreakPoint(__FILE__, __LINE__);
            return false;
        }
        break;
    case R4300i_ANDI:  case R4300i_ORI:    case R4300i_XORI:  case R4300i_LUI:
    case R4300i_ADDI:  case R4300i_ADDIU:  case R4300i_SLTI:  case R4300i_SLTIU:
    case R4300i_DADDI: case R4300i_DADDIU: case R4300i_LDL:   case R4300i_LDR:
    case R4300i_LB:    case R4300i_LH:     case R4300i_LWL:   case R4300i_LW:
    case R4300i_LBU:   case R4300i_LHU:    case R4300i_LWR:   case R4300i_LWU:
    case R4300i_SB:    case R4300i_SH:     case R4300i_SWL:   case R4300i_SW:
    case R4300i_SDL:   case R4300i_SDR:    case R4300i_SWR:   case R4300i_CACHE:
    case R4300i_LL:    case R4300i_LWC1:   case R4300i_LDC1:  case R4300i_LD:
    case R4300i_SC:    case R4300i_SWC1:   case R4300i_SDC1:  case R4300i_SD:
        break;
    case R4300i_BEQL:
        TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
        if (TargetPC == PC)
        {
            if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
            {
                PermLoop = true;
            }
        }
        if (Command.rs != 0 || Command.rt != 0)
        {
            ContinuePC = PC + 8;
        }
        IncludeDelaySlot = true;
        LikelyBranch = true;
        break;
    case R4300i_BNEL:
    case R4300i_BLEZL:
    case R4300i_BGTZL:
        TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
        ContinuePC = PC + 8;
        if (TargetPC == PC)
        {
            if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
            {
                PermLoop = true;
            }
        }
        LikelyBranch = true;
        IncludeDelaySlot = true;
        break;
    default:
        if (Command.Hex == 0x7C1C97C0 ||
            Command.Hex == 0xF1F3F5F7)
        {
            EndBlock = true;
            break;
        }
        g_Notify->BreakPoint(__FILE__, __LINE__);
        return false;
    }
    return true;
}