mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-29 09:09:52 -06:00
DSP: Fix sln file now that old LLE is dead. Add preliminary DSPAnalyzer, which looks for idle skip opportunities.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2930 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
104
Source/Plugins/Plugin_DSP_LLE-testing/Src/DSPAnalyzer.cpp
Normal file
104
Source/Plugins/Plugin_DSP_LLE-testing/Src/DSPAnalyzer.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "DSPAnalyzer.h"
|
||||
#include "DSPInterpreter.h"
|
||||
#include "DSPTables.h"
|
||||
#include "gdsp_memory.h"
|
||||
|
||||
namespace DSPAnalyzer {
|
||||
|
||||
// Holds data about all instructions in RAM.
|
||||
u8 inst_flags[ISPACE];
|
||||
|
||||
// Good candidates for idle skipping is mail wait loops. If we're time slicing
|
||||
// between the main CPU and the DSP, if the DSP runs into one of these, it might
|
||||
// as well give up its time slice immediately.
|
||||
|
||||
// Max signature length is 6. A 0 in a signature is ignored.
|
||||
#define NUM_IDLE_SIGS 2
|
||||
#define MAX_IDLE_SIG_SIZE 6
|
||||
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
|
||||
{
|
||||
{ 0x27fc, // LRS $31, @DMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029d, 0x027a, // JLZ 0x027a
|
||||
0x02df, 0 }, // RET
|
||||
{ 0x27fe, // LRS $31, @CMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029c, 0x0280, // JLNZ 0x0280
|
||||
0x02df, 0 }, // RET
|
||||
};
|
||||
|
||||
void Reset()
|
||||
{
|
||||
memset(inst_flags, 0, sizeof(inst_flags));
|
||||
}
|
||||
|
||||
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, but should be good
|
||||
// enough as a start.
|
||||
int addr = start_addr;
|
||||
while (addr < end_addr)
|
||||
{
|
||||
UDSPInstruction inst = dsp_imem_read(addr);
|
||||
const DSPOPCTemplate *opcode = GetOpTemplate(inst);
|
||||
if (!opcode)
|
||||
{
|
||||
addr++;
|
||||
continue;
|
||||
}
|
||||
inst_flags[addr] |= CODE_START_OF_INST;
|
||||
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] != dsp_imem_read(addr + i))
|
||||
break;
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
|
||||
inst_flags[addr] |= CODE_IDLE_SKIP;
|
||||
// TODO: actually use this flag somewhere.
|
||||
}
|
||||
}
|
||||
}
|
||||
NOTICE_LOG(DSPLLE, "Finished analysis.");
|
||||
}
|
||||
|
||||
void Analyze()
|
||||
{
|
||||
Reset();
|
||||
AnalyzeRange(0x0000, 0x1000); // IRAM
|
||||
AnalyzeRange(0x8000, 0x9000); // IROM
|
||||
}
|
||||
|
||||
} // namespace
|
Reference in New Issue
Block a user