std::string DSPDebugInterface::GetRawMemoryString(int memory, unsigned int address) { if (DSPCore_GetState() == State::Stopped) return ""; switch (memory) { case 0: // IMEM switch (address >> 12) { case 0: case 0x8: return StringFromFormat("%04x", dsp_imem_read(address)); default: return "--IMEM--"; } case 1: // DMEM switch (address >> 12) { case 0: case 1: return StringFromFormat("%04x (DMEM)", dsp_dmem_read(address)); case 0xf: return StringFromFormat("%04x (MMIO)", g_dsp.ifx_regs[address & 0xFF]); default: return "--DMEM--"; } } return ""; }
void DSPDebugInterface::GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size) { if (DSPCore_GetState() == DSPCORE_STOP) { dest[0] = 0; return; } switch (memory) { case 0: // IMEM switch (address >> 12) { case 0: case 0x8: sprintf(dest, "%04x", dsp_imem_read(address)); break; default: sprintf(dest, "--IMEM--"); break; } break; case 1: // DMEM switch (address >> 12) { case 0: case 1: sprintf(dest, "%04x (DMEM)", dsp_dmem_read(address)); break; case 0xf: sprintf(dest, "%04x (MMIO)", g_dsp.ifx_regs[address & 0xFF]); break; default: sprintf(dest, "--DMEM--"); break; } break; } }
static void AnalyzeRange(int start_addr, int end_addr) { // First we run an extremely simplified version of a disassembler to find // where all instructions start. // This may not be 100% accurate in case of jump tables! // It could get desynced, which would be bad. We'll see if that's an issue. u16 last_arithmetic = 0; for (int addr = start_addr; addr < end_addr;) { UDSPInstruction inst = dsp_imem_read(addr); const DSPOPCTemplate *opcode = GetOpTemplate(inst); if (!opcode) { addr++; continue; } code_flags[addr] |= CODE_START_OF_INST; // Look for loops. if ((inst & 0xffe0) == 0x0060 || (inst & 0xff00) == 0x1100) { // BLOOP, BLOOPI u16 loop_end = dsp_imem_read(addr + 1); code_flags[addr] |= CODE_LOOP_START; code_flags[loop_end] |= CODE_LOOP_END; } else if ((inst & 0xffe0) == 0x0040 || (inst & 0xff00) == 0x1000) { // LOOP, LOOPI code_flags[addr] |= CODE_LOOP_START; code_flags[addr + 1] |= CODE_LOOP_END; } // Mark the last arithmetic/multiplier instruction before a branch. // We must update the SR reg at these instructions if (opcode->updates_sr) { last_arithmetic = addr; } if (opcode->branch && !opcode->uncond_branch) { code_flags[last_arithmetic] |= CODE_UPDATE_SR; } // If an instruction potentially raises exceptions, mark the following // instruction as needing to check for exceptions if (opcode->opcode == 0x00c0 || opcode->opcode == 0x1800 || opcode->opcode == 0x1880 || opcode->opcode == 0x1900 || opcode->opcode == 0x1980 || opcode->opcode == 0x2000 || opcode->extended ) code_flags[addr + opcode->size] |= CODE_CHECK_INT; addr += opcode->size; } // Next, we'll scan for potential idle skips. for (int s = 0; s < NUM_IDLE_SIGS; s++) { for (int addr = start_addr; addr < end_addr; addr++) { bool found = false; for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++) { if (idle_skip_sigs[s][i] == 0) found = true; if (idle_skip_sigs[s][i] == 0xFFFF) continue; if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i)) break; } if (found) { INFO_LOG(DSPLLE, "Idle skip location found at %02x (sigNum:%d)", addr, s+1); code_flags[addr] |= CODE_IDLE_SKIP; } } } INFO_LOG(DSPLLE, "Finished analysis."); }