mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-22 22:00:39 -06:00
add *.user, Win32, and x64 build dir to ignore list for DebuggerUICommon and Unit Tests
add *.aps to ignore list for DolphinWX dir add eol-style native to 120 or so files git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3689 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -1,133 +1,133 @@
|
||||
// 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 "DSPMemoryMap.h"
|
||||
|
||||
namespace DSPAnalyzer {
|
||||
|
||||
// Holds data about all instructions in RAM.
|
||||
u8 code_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, after executing once.
|
||||
|
||||
// Max signature length is 6. A 0 in a signature is ignored.
|
||||
#define NUM_IDLE_SIGS 5
|
||||
#define MAX_IDLE_SIG_SIZE 6
|
||||
|
||||
// 0xFFFF means ignore.
|
||||
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
|
||||
{
|
||||
// From AX:
|
||||
{ 0x26fc, // LRS $30, @DMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x27fc, // LRS $31, @DMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x26fe, // LRS $30, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
{ 0x27fe, // LRS $31, @CMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
|
||||
// From Zelda:
|
||||
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x05cf
|
||||
0 }
|
||||
};
|
||||
|
||||
void Reset()
|
||||
{
|
||||
memset(code_flags, 0, sizeof(code_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!
|
||||
// It could get desynced, which would be bad. We'll see if that's an issue.
|
||||
int addr = start_addr;
|
||||
while (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;
|
||||
addr += opcode->size;
|
||||
|
||||
// Look for loops.
|
||||
if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
|
||||
// BLOOP, BLOOPI
|
||||
u16 loop_end = dsp_imem_read(addr + 1);
|
||||
code_flags[loop_end] |= CODE_LOOP_END;
|
||||
} else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
|
||||
// LOOP, LOOPI
|
||||
code_flags[addr + 1] |= CODE_LOOP_END;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
|
||||
code_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
|
||||
// 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 "DSPMemoryMap.h"
|
||||
|
||||
namespace DSPAnalyzer {
|
||||
|
||||
// Holds data about all instructions in RAM.
|
||||
u8 code_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, after executing once.
|
||||
|
||||
// Max signature length is 6. A 0 in a signature is ignored.
|
||||
#define NUM_IDLE_SIGS 5
|
||||
#define MAX_IDLE_SIG_SIZE 6
|
||||
|
||||
// 0xFFFF means ignore.
|
||||
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
|
||||
{
|
||||
// From AX:
|
||||
{ 0x26fc, // LRS $30, @DMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x27fc, // LRS $31, @DMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x26fe, // LRS $30, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
{ 0x27fe, // LRS $31, @CMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
|
||||
// From Zelda:
|
||||
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x05cf
|
||||
0 }
|
||||
};
|
||||
|
||||
void Reset()
|
||||
{
|
||||
memset(code_flags, 0, sizeof(code_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!
|
||||
// It could get desynced, which would be bad. We'll see if that's an issue.
|
||||
int addr = start_addr;
|
||||
while (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;
|
||||
addr += opcode->size;
|
||||
|
||||
// Look for loops.
|
||||
if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
|
||||
// BLOOP, BLOOPI
|
||||
u16 loop_end = dsp_imem_read(addr + 1);
|
||||
code_flags[loop_end] |= CODE_LOOP_END;
|
||||
} else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
|
||||
// LOOP, LOOPI
|
||||
code_flags[addr + 1] |= CODE_LOOP_END;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
|
||||
code_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
|
||||
|
@ -1,49 +1,49 @@
|
||||
// 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/
|
||||
|
||||
// Basic code analysis.
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
namespace DSPAnalyzer {
|
||||
|
||||
#define ISPACE 65536
|
||||
|
||||
// Useful things to detect:
|
||||
// * Loop endpoints - so that we can avoid checking for loops every cycle.
|
||||
|
||||
enum
|
||||
{
|
||||
CODE_START_OF_INST = 1,
|
||||
CODE_IDLE_SKIP = 2,
|
||||
CODE_LOOP_END = 4,
|
||||
};
|
||||
|
||||
// Easy to query array covering the whole of instruction memory.
|
||||
// Just index by address.
|
||||
// This one will be helpful for debuggers and jits.
|
||||
extern u8 code_flags[ISPACE];
|
||||
|
||||
// This one should be called every time IRAM changes - which is basically
|
||||
// every time that a new ucode gets uploaded, and never else. At that point,
|
||||
// we can do as much static analysis as we want - but we should always throw
|
||||
// all old analysis away. Luckily the entire address space is only 64K code
|
||||
// words and the actual code space 8K instructions in total, so we can do
|
||||
// some pretty expensive analysis if necessary.
|
||||
void Analyze();
|
||||
|
||||
} // namespace
|
||||
// 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/
|
||||
|
||||
// Basic code analysis.
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
namespace DSPAnalyzer {
|
||||
|
||||
#define ISPACE 65536
|
||||
|
||||
// Useful things to detect:
|
||||
// * Loop endpoints - so that we can avoid checking for loops every cycle.
|
||||
|
||||
enum
|
||||
{
|
||||
CODE_START_OF_INST = 1,
|
||||
CODE_IDLE_SKIP = 2,
|
||||
CODE_LOOP_END = 4,
|
||||
};
|
||||
|
||||
// Easy to query array covering the whole of instruction memory.
|
||||
// Just index by address.
|
||||
// This one will be helpful for debuggers and jits.
|
||||
extern u8 code_flags[ISPACE];
|
||||
|
||||
// This one should be called every time IRAM changes - which is basically
|
||||
// every time that a new ucode gets uploaded, and never else. At that point,
|
||||
// we can do as much static analysis as we want - but we should always throw
|
||||
// all old analysis away. Luckily the entire address space is only 64K code
|
||||
// words and the actual code space 8K instructions in total, so we can do
|
||||
// some pretty expensive analysis if necessary.
|
||||
void Analyze();
|
||||
|
||||
} // namespace
|
||||
|
@ -1,19 +1,19 @@
|
||||
// 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 "DSPBreakpoints.h"
|
||||
|
||||
// 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 "DSPBreakpoints.h"
|
||||
|
||||
|
@ -1,63 +1,63 @@
|
||||
// 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/
|
||||
|
||||
#ifndef _DSP_BREAKPOINTS
|
||||
#define _DSP_BREAKPOINTS
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// super fast breakpoints for a limited range.
|
||||
// To be used interchangably with the BreakPoints class.
|
||||
class DSPBreakpoints
|
||||
{
|
||||
public:
|
||||
DSPBreakpoints() {Clear();}
|
||||
// is address breakpoint
|
||||
bool IsAddressBreakPoint(u32 addr) {
|
||||
return b[addr] != 0;
|
||||
}
|
||||
|
||||
// AddBreakPoint
|
||||
bool Add(u32 addr, bool temp=false) {
|
||||
bool was_one = b[addr] != 0;
|
||||
if (!was_one) {
|
||||
b[addr] = temp ? 2 : 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Remove Breakpoint
|
||||
bool Remove(u32 addr) {
|
||||
bool was_one = b[addr] != 0;
|
||||
b[addr] = 0;
|
||||
return was_one;
|
||||
}
|
||||
void Clear() {
|
||||
for (int i = 0; i < 65536; i++)
|
||||
b[i] = 0;
|
||||
}
|
||||
|
||||
void DeleteByAddress(u32 addr) {
|
||||
b[addr] = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
u8 b[65536];
|
||||
};
|
||||
|
||||
#endif
|
||||
// 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/
|
||||
|
||||
#ifndef _DSP_BREAKPOINTS
|
||||
#define _DSP_BREAKPOINTS
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// super fast breakpoints for a limited range.
|
||||
// To be used interchangably with the BreakPoints class.
|
||||
class DSPBreakpoints
|
||||
{
|
||||
public:
|
||||
DSPBreakpoints() {Clear();}
|
||||
// is address breakpoint
|
||||
bool IsAddressBreakPoint(u32 addr) {
|
||||
return b[addr] != 0;
|
||||
}
|
||||
|
||||
// AddBreakPoint
|
||||
bool Add(u32 addr, bool temp=false) {
|
||||
bool was_one = b[addr] != 0;
|
||||
if (!was_one) {
|
||||
b[addr] = temp ? 2 : 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Remove Breakpoint
|
||||
bool Remove(u32 addr) {
|
||||
bool was_one = b[addr] != 0;
|
||||
b[addr] = 0;
|
||||
return was_one;
|
||||
}
|
||||
void Clear() {
|
||||
for (int i = 0; i < 65536; i++)
|
||||
b[i] = 0;
|
||||
}
|
||||
|
||||
void DeleteByAddress(u32 addr) {
|
||||
b[addr] = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
u8 b[65536];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,235 +1,235 @@
|
||||
// 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 <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "StringUtil.h"
|
||||
#include "DSPCodeUtil.h"
|
||||
#include "assemble.h"
|
||||
#include "disassemble.h"
|
||||
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> &code)
|
||||
{
|
||||
AssemblerSettings settings;
|
||||
settings.pc = 0;
|
||||
// settings.decode_registers = false;
|
||||
// settings.decode_names = false;
|
||||
settings.print_tabs = false;
|
||||
settings.ext_separator = '\'';
|
||||
|
||||
// TODO: fix the terrible api of the assembler.
|
||||
DSPAssembler assembler(settings);
|
||||
if (!assembler.Assemble(text, code)) {
|
||||
std::cerr << assembler.GetErrorString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
|
||||
{
|
||||
if (code.empty())
|
||||
return false;
|
||||
|
||||
AssemblerSettings settings;
|
||||
|
||||
// These two prevent roundtripping.
|
||||
settings.show_hex = false;
|
||||
settings.show_pc = line_numbers;
|
||||
settings.ext_separator = '\'';
|
||||
settings.decode_names = false;
|
||||
settings.decode_registers = true;
|
||||
|
||||
DSPDisassembler disasm(settings);
|
||||
bool success = disasm.Disassemble(0, code, 0x0000, text);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
|
||||
{
|
||||
if (code1.size() != code2.size())
|
||||
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
|
||||
u32 count_equal = 0;
|
||||
const int min_size = (int)std::min(code1.size(), code2.size());
|
||||
|
||||
AssemblerSettings settings;
|
||||
DSPDisassembler disassembler(settings);
|
||||
for (int i = 0; i < min_size; i++)
|
||||
{
|
||||
if (code1[i] == code2[i])
|
||||
count_equal++;
|
||||
else
|
||||
{
|
||||
std::string line1, line2;
|
||||
u16 pc = i;
|
||||
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
|
||||
pc = i;
|
||||
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
|
||||
printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
|
||||
}
|
||||
}
|
||||
if (code2.size() != code1.size())
|
||||
{
|
||||
printf("Extra code words:\n");
|
||||
const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
|
||||
for (int i = min_size; i < (int)longest.size(); i++)
|
||||
{
|
||||
u16 pc = i;
|
||||
std::string line;
|
||||
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
|
||||
printf("!! %s\n", line.c_str());
|
||||
}
|
||||
}
|
||||
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
|
||||
return code1.size() == code2.size() && code1.size() == count_equal;
|
||||
}
|
||||
|
||||
void GenRandomCode(int size, std::vector<u16> &code)
|
||||
{
|
||||
code.resize(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
code[i] = rand() ^ (rand() << 8);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||
const char *name, std::string &header)
|
||||
{
|
||||
std::vector<u16> code_copy = code;
|
||||
// Add some nops at the end to align the size a bit.
|
||||
while (code_copy.size() & 7)
|
||||
code_copy.push_back(0);
|
||||
char buffer[1024];
|
||||
header.clear();
|
||||
header.reserve(code.size() * 4);
|
||||
header.append("#define NUM_UCODES 1\n\n");
|
||||
std::string filename;
|
||||
SplitPath(_filename, NULL, &filename, NULL);
|
||||
header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
|
||||
header.append("#ifndef _MSCVER\n");
|
||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
|
||||
header.append("#else\n");
|
||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||
header.append("#endif\n\n");
|
||||
|
||||
header.append("\t{\n\t\t");
|
||||
for (u32 j = 0; j < code.size(); j++)
|
||||
{
|
||||
if (j && ((j & 15) == 0))
|
||||
header.append("\n\t\t");
|
||||
sprintf(buffer, "0x%04x, ", code[j]);
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("\n\t},\n");
|
||||
|
||||
header.append("};\n");
|
||||
}
|
||||
|
||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
|
||||
int numCodes, const char *name, std::string &header)
|
||||
{
|
||||
char buffer[1024];
|
||||
int reserveSize = 0;
|
||||
for(int i = 0; i < numCodes; i++)
|
||||
reserveSize += (int)codes[i].size();
|
||||
|
||||
|
||||
header.clear();
|
||||
header.reserve(reserveSize * 4);
|
||||
sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
|
||||
header.append(buffer);
|
||||
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
|
||||
for (int i = 0; i < numCodes; i++)
|
||||
{
|
||||
std::string filename;
|
||||
if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
|
||||
filename = filenames->at(i);
|
||||
sprintf(buffer, "\t\"%s\",\n", filename.c_str());
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("};\n\n");
|
||||
header.append("#ifndef _MSCVER\n");
|
||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
|
||||
header.append("#else\n");
|
||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||
header.append("#endif\n\n");
|
||||
|
||||
for(int i = 0; i < numCodes; i++) {
|
||||
if(codes[i].size() == 0)
|
||||
continue;
|
||||
|
||||
std::vector<u16> code_copy = codes[i];
|
||||
// Add some nops at the end to align the size a bit.
|
||||
while (code_copy.size() & 7)
|
||||
code_copy.push_back(0);
|
||||
|
||||
header.append("\t{\n\t\t");
|
||||
for (u32 j = 0; j < codes[i].size(); j++)
|
||||
{
|
||||
if (j && ((j & 15) == 0))
|
||||
header.append("\n\t\t");
|
||||
sprintf(buffer, "0x%04x, ", codes[i][j]);
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("\n\t},\n");
|
||||
}
|
||||
header.append("};\n");
|
||||
}
|
||||
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
|
||||
{
|
||||
str.resize(code.size() * 2);
|
||||
for (int i = 0; i < (int)code.size(); i++)
|
||||
{
|
||||
str[i * 2 + 0] = code[i] >> 8;
|
||||
str[i * 2 + 1] = code[i] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
|
||||
{
|
||||
code.resize(str.size() / 2);
|
||||
for (int i = 0; i < (int)code.size(); i++)
|
||||
{
|
||||
code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadBinary(const char *filename, std::vector<u16> &code)
|
||||
{
|
||||
std::string buffer;
|
||||
if (!File::ReadFileToString(false, filename, buffer))
|
||||
return false;
|
||||
|
||||
BinaryStringBEToCode(buffer, code);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename)
|
||||
{
|
||||
std::string buffer;
|
||||
CodeToBinaryStringBE(code, buffer);
|
||||
if (!File::WriteStringToFile(false, buffer, filename))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// 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 <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "StringUtil.h"
|
||||
#include "DSPCodeUtil.h"
|
||||
#include "assemble.h"
|
||||
#include "disassemble.h"
|
||||
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> &code)
|
||||
{
|
||||
AssemblerSettings settings;
|
||||
settings.pc = 0;
|
||||
// settings.decode_registers = false;
|
||||
// settings.decode_names = false;
|
||||
settings.print_tabs = false;
|
||||
settings.ext_separator = '\'';
|
||||
|
||||
// TODO: fix the terrible api of the assembler.
|
||||
DSPAssembler assembler(settings);
|
||||
if (!assembler.Assemble(text, code)) {
|
||||
std::cerr << assembler.GetErrorString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
|
||||
{
|
||||
if (code.empty())
|
||||
return false;
|
||||
|
||||
AssemblerSettings settings;
|
||||
|
||||
// These two prevent roundtripping.
|
||||
settings.show_hex = false;
|
||||
settings.show_pc = line_numbers;
|
||||
settings.ext_separator = '\'';
|
||||
settings.decode_names = false;
|
||||
settings.decode_registers = true;
|
||||
|
||||
DSPDisassembler disasm(settings);
|
||||
bool success = disasm.Disassemble(0, code, 0x0000, text);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
|
||||
{
|
||||
if (code1.size() != code2.size())
|
||||
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
|
||||
u32 count_equal = 0;
|
||||
const int min_size = (int)std::min(code1.size(), code2.size());
|
||||
|
||||
AssemblerSettings settings;
|
||||
DSPDisassembler disassembler(settings);
|
||||
for (int i = 0; i < min_size; i++)
|
||||
{
|
||||
if (code1[i] == code2[i])
|
||||
count_equal++;
|
||||
else
|
||||
{
|
||||
std::string line1, line2;
|
||||
u16 pc = i;
|
||||
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
|
||||
pc = i;
|
||||
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
|
||||
printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
|
||||
}
|
||||
}
|
||||
if (code2.size() != code1.size())
|
||||
{
|
||||
printf("Extra code words:\n");
|
||||
const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
|
||||
for (int i = min_size; i < (int)longest.size(); i++)
|
||||
{
|
||||
u16 pc = i;
|
||||
std::string line;
|
||||
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
|
||||
printf("!! %s\n", line.c_str());
|
||||
}
|
||||
}
|
||||
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
|
||||
return code1.size() == code2.size() && code1.size() == count_equal;
|
||||
}
|
||||
|
||||
void GenRandomCode(int size, std::vector<u16> &code)
|
||||
{
|
||||
code.resize(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
code[i] = rand() ^ (rand() << 8);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||
const char *name, std::string &header)
|
||||
{
|
||||
std::vector<u16> code_copy = code;
|
||||
// Add some nops at the end to align the size a bit.
|
||||
while (code_copy.size() & 7)
|
||||
code_copy.push_back(0);
|
||||
char buffer[1024];
|
||||
header.clear();
|
||||
header.reserve(code.size() * 4);
|
||||
header.append("#define NUM_UCODES 1\n\n");
|
||||
std::string filename;
|
||||
SplitPath(_filename, NULL, &filename, NULL);
|
||||
header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
|
||||
header.append("#ifndef _MSCVER\n");
|
||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
|
||||
header.append("#else\n");
|
||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||
header.append("#endif\n\n");
|
||||
|
||||
header.append("\t{\n\t\t");
|
||||
for (u32 j = 0; j < code.size(); j++)
|
||||
{
|
||||
if (j && ((j & 15) == 0))
|
||||
header.append("\n\t\t");
|
||||
sprintf(buffer, "0x%04x, ", code[j]);
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("\n\t},\n");
|
||||
|
||||
header.append("};\n");
|
||||
}
|
||||
|
||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
|
||||
int numCodes, const char *name, std::string &header)
|
||||
{
|
||||
char buffer[1024];
|
||||
int reserveSize = 0;
|
||||
for(int i = 0; i < numCodes; i++)
|
||||
reserveSize += (int)codes[i].size();
|
||||
|
||||
|
||||
header.clear();
|
||||
header.reserve(reserveSize * 4);
|
||||
sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
|
||||
header.append(buffer);
|
||||
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
|
||||
for (int i = 0; i < numCodes; i++)
|
||||
{
|
||||
std::string filename;
|
||||
if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
|
||||
filename = filenames->at(i);
|
||||
sprintf(buffer, "\t\"%s\",\n", filename.c_str());
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("};\n\n");
|
||||
header.append("#ifndef _MSCVER\n");
|
||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
|
||||
header.append("#else\n");
|
||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||
header.append("#endif\n\n");
|
||||
|
||||
for(int i = 0; i < numCodes; i++) {
|
||||
if(codes[i].size() == 0)
|
||||
continue;
|
||||
|
||||
std::vector<u16> code_copy = codes[i];
|
||||
// Add some nops at the end to align the size a bit.
|
||||
while (code_copy.size() & 7)
|
||||
code_copy.push_back(0);
|
||||
|
||||
header.append("\t{\n\t\t");
|
||||
for (u32 j = 0; j < codes[i].size(); j++)
|
||||
{
|
||||
if (j && ((j & 15) == 0))
|
||||
header.append("\n\t\t");
|
||||
sprintf(buffer, "0x%04x, ", codes[i][j]);
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("\n\t},\n");
|
||||
}
|
||||
header.append("};\n");
|
||||
}
|
||||
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
|
||||
{
|
||||
str.resize(code.size() * 2);
|
||||
for (int i = 0; i < (int)code.size(); i++)
|
||||
{
|
||||
str[i * 2 + 0] = code[i] >> 8;
|
||||
str[i * 2 + 1] = code[i] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
|
||||
{
|
||||
code.resize(str.size() / 2);
|
||||
for (int i = 0; i < (int)code.size(); i++)
|
||||
{
|
||||
code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadBinary(const char *filename, std::vector<u16> &code)
|
||||
{
|
||||
std::string buffer;
|
||||
if (!File::ReadFileToString(false, filename, buffer))
|
||||
return false;
|
||||
|
||||
BinaryStringBEToCode(buffer, code);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename)
|
||||
{
|
||||
std::string buffer;
|
||||
CodeToBinaryStringBE(code, buffer);
|
||||
if (!File::WriteStringToFile(false, buffer, filename))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,43 +1,43 @@
|
||||
// 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/
|
||||
|
||||
#ifndef _DSPCODEUTIL_H
|
||||
#define _DSPCODEUTIL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> &code);
|
||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
|
||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
|
||||
void GenRandomCode(int size, std::vector<u16> &code);
|
||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||
const char *name, std::string &header);
|
||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
|
||||
int numCodes, const char *name, std::string &header);
|
||||
|
||||
// Big-endian, for writing straight to file using File::WriteStringToFile.
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
|
||||
|
||||
// Load code (big endian binary).
|
||||
bool LoadBinary(const char *filename, std::vector<u16> &code);
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename);
|
||||
|
||||
#endif // _DSPCODEUTIL_H
|
||||
// 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/
|
||||
|
||||
#ifndef _DSPCODEUTIL_H
|
||||
#define _DSPCODEUTIL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> &code);
|
||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
|
||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
|
||||
void GenRandomCode(int size, std::vector<u16> &code);
|
||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||
const char *name, std::string &header);
|
||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
|
||||
int numCodes, const char *name, std::string &header);
|
||||
|
||||
// Big-endian, for writing straight to file using File::WriteStringToFile.
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
|
||||
|
||||
// Load code (big endian binary).
|
||||
bool LoadBinary(const char *filename, std::vector<u16> &code);
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename);
|
||||
|
||||
#endif // _DSPCODEUTIL_H
|
||||
|
@ -1,256 +1,256 @@
|
||||
/*====================================================================
|
||||
|
||||
filename: gdsp_interpreter.cpp
|
||||
project: GCemu
|
||||
created: 2004-6-18
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie & Tratax
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Thread.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPHost.h"
|
||||
#include "DSPAnalyzer.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
#include "DSPHWInterface.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
SDSP g_dsp;
|
||||
DSPBreakpoints dsp_breakpoints;
|
||||
DSPCoreState core_state = DSPCORE_RUNNING;
|
||||
Common::Event step_event;
|
||||
|
||||
static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
|
||||
{
|
||||
FILE *pFile = fopen(fname, "rb");
|
||||
const size_t size_in_bytes = size_in_words * sizeof(u16);
|
||||
if (pFile)
|
||||
{
|
||||
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
|
||||
if (read_bytes != size_in_bytes)
|
||||
{
|
||||
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
fclose(pFile);
|
||||
|
||||
// Byteswap the rom.
|
||||
for (int i = 0; i < DSP_IROM_SIZE; i++)
|
||||
rom[i] = Common::swap16(rom[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
// Always keep ROMs write protected.
|
||||
WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
|
||||
{
|
||||
g_dsp.step_counter = 0;
|
||||
|
||||
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
|
||||
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
|
||||
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
|
||||
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
|
||||
|
||||
// Fill roms with zeros.
|
||||
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
|
||||
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
|
||||
|
||||
// Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
|
||||
LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
|
||||
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
g_dsp.r[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
g_dsp.reg_stack_ptr[i] = 0;
|
||||
for (int j = 0; j < DSP_STACK_DEPTH; j++)
|
||||
{
|
||||
g_dsp.reg_stack[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill IRAM with HALT opcodes.
|
||||
for (int i = 0; i < DSP_IRAM_SIZE; i++)
|
||||
{
|
||||
g_dsp.iram[i] = 0x0021; // HALT opcode
|
||||
}
|
||||
|
||||
// Just zero out DRAM.
|
||||
for (int i = 0; i < DSP_DRAM_SIZE; i++)
|
||||
{
|
||||
g_dsp.dram[i] = 0;
|
||||
}
|
||||
|
||||
// Copied from a real console after the custom UCode has been loaded.
|
||||
// These are the indexing wrapping registers.
|
||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||
|
||||
g_dsp.cr = 0x804;
|
||||
gdsp_ifx_init();
|
||||
|
||||
// Mostly keep IRAM write protected. We unprotect only when DMA-ing
|
||||
// in new ucodes.
|
||||
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
|
||||
DSPAnalyzer::Analyze();
|
||||
|
||||
step_event.Init();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSPCore_Shutdown()
|
||||
{
|
||||
step_event.Shutdown();
|
||||
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
|
||||
}
|
||||
|
||||
void DSPCore_Reset()
|
||||
{
|
||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
|
||||
g_dsp.pc = DSP_RESET_VECTOR;
|
||||
g_dsp.exception_in_progress_hack = false;
|
||||
|
||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||
|
||||
}
|
||||
|
||||
void DSPCore_SetException(u8 level)
|
||||
{
|
||||
g_dsp.exceptions |= 1 << level;
|
||||
}
|
||||
|
||||
void DSPCore_CheckExternalInterrupt()
|
||||
{
|
||||
// check if there is an external interrupt
|
||||
if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
|
||||
{
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "trying External interupt fired");
|
||||
#endif
|
||||
if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
|
||||
{
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "External interupt fired");
|
||||
#endif
|
||||
// level 7 is the interrupt exception
|
||||
DSPCore_SetException(EXP_INT);
|
||||
|
||||
g_dsp.cr &= ~CR_EXTERNAL_INT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSPCore_CheckExceptions()
|
||||
{
|
||||
if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
|
||||
#endif
|
||||
// check exceptions
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// Seems 7 must pass or zelda dies
|
||||
if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
|
||||
if (g_dsp.exceptions & (1 << i)) {
|
||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
|
||||
|
||||
g_dsp.pc = i * 2;
|
||||
g_dsp.exceptions &= ~(1 << i);
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "exception %d fired");
|
||||
#endif
|
||||
g_dsp.exception_in_progress_hack = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delegate to JIT (when it is written) or interpreter as appropriate.
|
||||
// Handle state changes and stepping.
|
||||
int DSPCore_RunCycles(int cycles)
|
||||
{
|
||||
while (cycles > 0) {
|
||||
reswitch:
|
||||
switch (core_state)
|
||||
{
|
||||
case DSPCORE_RUNNING:
|
||||
#if 1 // Set to 0 to disable breakpoints, for a speed boost.
|
||||
cycles = DSPInterpreter::RunCyclesDebug(cycles);
|
||||
#else
|
||||
cycles = DSPInterpreter::RunCycles(cycles);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DSPCORE_STEPPING:
|
||||
step_event.Wait();
|
||||
if (core_state != DSPCORE_STEPPING)
|
||||
goto reswitch;
|
||||
|
||||
DSPInterpreter::Step();
|
||||
cycles--;
|
||||
|
||||
DSPHost_UpdateDebugger();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cycles;
|
||||
}
|
||||
|
||||
void DSPCore_SetState(DSPCoreState new_state)
|
||||
{
|
||||
core_state = new_state;
|
||||
// kick the event, in case we are waiting
|
||||
if (new_state == DSPCORE_RUNNING)
|
||||
step_event.Set();
|
||||
// Sleep(10);
|
||||
DSPHost_UpdateDebugger();
|
||||
}
|
||||
|
||||
DSPCoreState DSPCore_GetState()
|
||||
{
|
||||
return core_state;
|
||||
}
|
||||
|
||||
void DSPCore_Step()
|
||||
{
|
||||
if (core_state == DSPCORE_STEPPING)
|
||||
step_event.Set();
|
||||
}
|
||||
/*====================================================================
|
||||
|
||||
filename: gdsp_interpreter.cpp
|
||||
project: GCemu
|
||||
created: 2004-6-18
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie & Tratax
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Thread.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPHost.h"
|
||||
#include "DSPAnalyzer.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
#include "DSPHWInterface.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
SDSP g_dsp;
|
||||
DSPBreakpoints dsp_breakpoints;
|
||||
DSPCoreState core_state = DSPCORE_RUNNING;
|
||||
Common::Event step_event;
|
||||
|
||||
static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
|
||||
{
|
||||
FILE *pFile = fopen(fname, "rb");
|
||||
const size_t size_in_bytes = size_in_words * sizeof(u16);
|
||||
if (pFile)
|
||||
{
|
||||
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
|
||||
if (read_bytes != size_in_bytes)
|
||||
{
|
||||
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
fclose(pFile);
|
||||
|
||||
// Byteswap the rom.
|
||||
for (int i = 0; i < DSP_IROM_SIZE; i++)
|
||||
rom[i] = Common::swap16(rom[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
// Always keep ROMs write protected.
|
||||
WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
|
||||
{
|
||||
g_dsp.step_counter = 0;
|
||||
|
||||
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
|
||||
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
|
||||
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
|
||||
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
|
||||
|
||||
// Fill roms with zeros.
|
||||
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
|
||||
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
|
||||
|
||||
// Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
|
||||
LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
|
||||
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
g_dsp.r[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
g_dsp.reg_stack_ptr[i] = 0;
|
||||
for (int j = 0; j < DSP_STACK_DEPTH; j++)
|
||||
{
|
||||
g_dsp.reg_stack[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill IRAM with HALT opcodes.
|
||||
for (int i = 0; i < DSP_IRAM_SIZE; i++)
|
||||
{
|
||||
g_dsp.iram[i] = 0x0021; // HALT opcode
|
||||
}
|
||||
|
||||
// Just zero out DRAM.
|
||||
for (int i = 0; i < DSP_DRAM_SIZE; i++)
|
||||
{
|
||||
g_dsp.dram[i] = 0;
|
||||
}
|
||||
|
||||
// Copied from a real console after the custom UCode has been loaded.
|
||||
// These are the indexing wrapping registers.
|
||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||
|
||||
g_dsp.cr = 0x804;
|
||||
gdsp_ifx_init();
|
||||
|
||||
// Mostly keep IRAM write protected. We unprotect only when DMA-ing
|
||||
// in new ucodes.
|
||||
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
|
||||
DSPAnalyzer::Analyze();
|
||||
|
||||
step_event.Init();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSPCore_Shutdown()
|
||||
{
|
||||
step_event.Shutdown();
|
||||
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
|
||||
}
|
||||
|
||||
void DSPCore_Reset()
|
||||
{
|
||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
|
||||
g_dsp.pc = DSP_RESET_VECTOR;
|
||||
g_dsp.exception_in_progress_hack = false;
|
||||
|
||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||
|
||||
}
|
||||
|
||||
void DSPCore_SetException(u8 level)
|
||||
{
|
||||
g_dsp.exceptions |= 1 << level;
|
||||
}
|
||||
|
||||
void DSPCore_CheckExternalInterrupt()
|
||||
{
|
||||
// check if there is an external interrupt
|
||||
if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
|
||||
{
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "trying External interupt fired");
|
||||
#endif
|
||||
if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
|
||||
{
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "External interupt fired");
|
||||
#endif
|
||||
// level 7 is the interrupt exception
|
||||
DSPCore_SetException(EXP_INT);
|
||||
|
||||
g_dsp.cr &= ~CR_EXTERNAL_INT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSPCore_CheckExceptions()
|
||||
{
|
||||
if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
|
||||
#endif
|
||||
// check exceptions
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// Seems 7 must pass or zelda dies
|
||||
if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
|
||||
if (g_dsp.exceptions & (1 << i)) {
|
||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
|
||||
|
||||
g_dsp.pc = i * 2;
|
||||
g_dsp.exceptions &= ~(1 << i);
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "exception %d fired");
|
||||
#endif
|
||||
g_dsp.exception_in_progress_hack = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delegate to JIT (when it is written) or interpreter as appropriate.
|
||||
// Handle state changes and stepping.
|
||||
int DSPCore_RunCycles(int cycles)
|
||||
{
|
||||
while (cycles > 0) {
|
||||
reswitch:
|
||||
switch (core_state)
|
||||
{
|
||||
case DSPCORE_RUNNING:
|
||||
#if 1 // Set to 0 to disable breakpoints, for a speed boost.
|
||||
cycles = DSPInterpreter::RunCyclesDebug(cycles);
|
||||
#else
|
||||
cycles = DSPInterpreter::RunCycles(cycles);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DSPCORE_STEPPING:
|
||||
step_event.Wait();
|
||||
if (core_state != DSPCORE_STEPPING)
|
||||
goto reswitch;
|
||||
|
||||
DSPInterpreter::Step();
|
||||
cycles--;
|
||||
|
||||
DSPHost_UpdateDebugger();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cycles;
|
||||
}
|
||||
|
||||
void DSPCore_SetState(DSPCoreState new_state)
|
||||
{
|
||||
core_state = new_state;
|
||||
// kick the event, in case we are waiting
|
||||
if (new_state == DSPCORE_RUNNING)
|
||||
step_event.Set();
|
||||
// Sleep(10);
|
||||
DSPHost_UpdateDebugger();
|
||||
}
|
||||
|
||||
DSPCoreState DSPCore_GetState()
|
||||
{
|
||||
return core_state;
|
||||
}
|
||||
|
||||
void DSPCore_Step()
|
||||
{
|
||||
if (core_state == DSPCORE_STEPPING)
|
||||
step_event.Set();
|
||||
}
|
||||
|
@ -1,240 +1,240 @@
|
||||
/*====================================================================
|
||||
|
||||
filename: DSPCore.h
|
||||
project: GCemu
|
||||
created: 2004-6-18
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie & Tratax
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#ifndef _DSPCORE_H
|
||||
#define _DSPCORE_H
|
||||
|
||||
#include "DSPBreakpoints.h"
|
||||
|
||||
#define DSP_IRAM_BYTE_SIZE 0x2000
|
||||
#define DSP_IRAM_SIZE 0x1000
|
||||
#define DSP_IRAM_MASK 0x0fff
|
||||
|
||||
#define DSP_IROM_BYTE_SIZE 0x2000
|
||||
#define DSP_IROM_SIZE 0x1000
|
||||
#define DSP_IROM_MASK 0x0fff
|
||||
|
||||
#define DSP_DRAM_BYTE_SIZE 0x2000
|
||||
#define DSP_DRAM_SIZE 0x1000
|
||||
#define DSP_DRAM_MASK 0x0fff
|
||||
|
||||
#define DSP_COEF_BYTE_SIZE 0x2000
|
||||
#define DSP_COEF_SIZE 0x1000
|
||||
#define DSP_COEF_MASK 0x0fff
|
||||
|
||||
#define DSP_RESET_VECTOR 0x8000
|
||||
|
||||
#define DSP_STACK_DEPTH 0x20
|
||||
#define DSP_STACK_MASK 0x1f
|
||||
|
||||
#define DSP_CR_IMEM 2
|
||||
#define DSP_CR_DMEM 0
|
||||
#define DSP_CR_TO_CPU 1
|
||||
#define DSP_CR_FROM_CPU 0
|
||||
|
||||
|
||||
// Register table taken from libasnd
|
||||
#define DSP_REG_AR0 0x00 // address registers
|
||||
#define DSP_REG_AR1 0x01
|
||||
#define DSP_REG_AR2 0x02
|
||||
#define DSP_REG_AR3 0x03
|
||||
|
||||
#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
|
||||
#define DSP_REG_IX1 0x05
|
||||
#define DSP_REG_IX2 0x06
|
||||
#define DSP_REG_IX3 0x07
|
||||
|
||||
#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
|
||||
#define DSP_REG_WR1 0x09
|
||||
#define DSP_REG_WR2 0x0a
|
||||
#define DSP_REG_WR3 0x0b
|
||||
|
||||
#define DSP_REG_ST0 0x0c // stacks.
|
||||
#define DSP_REG_ST1 0x0d
|
||||
#define DSP_REG_ST2 0x0e
|
||||
#define DSP_REG_ST3 0x0f
|
||||
|
||||
#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
|
||||
#define DSP_REG_SR 0x13
|
||||
|
||||
#define DSP_REG_PRODL 0x14 // product.
|
||||
#define DSP_REG_PRODM 0x15
|
||||
#define DSP_REG_PRODH 0x16
|
||||
#define DSP_REG_PRODM2 0x17
|
||||
|
||||
#define DSP_REG_AXL0 0x18
|
||||
#define DSP_REG_AXL1 0x19
|
||||
#define DSP_REG_AXH0 0x1a
|
||||
#define DSP_REG_AXH1 0x1b
|
||||
|
||||
#define DSP_REG_ACC0 0x1c // accumulator (global)
|
||||
#define DSP_REG_ACC1 0x1d
|
||||
|
||||
#define DSP_REG_ACL0 0x1c // Low accumulator
|
||||
#define DSP_REG_ACL1 0x1d
|
||||
#define DSP_REG_ACM0 0x1e // Mid accumulator
|
||||
#define DSP_REG_ACM1 0x1f
|
||||
#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
|
||||
#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
|
||||
|
||||
// Hardware registers address
|
||||
|
||||
#define DSP_COEF_A1_0 0xa0
|
||||
|
||||
#define DSP_DSMAH 0xce
|
||||
#define DSP_DSMAL 0xcf
|
||||
#define DSP_DSCR 0xc9 // DSP DMA Control Reg
|
||||
#define DSP_DSPA 0xcd // DSP DMA Block Length
|
||||
#define DSP_DSBL 0xcb // DSP DMA DMEM Address
|
||||
#define DSP_DSMAH 0xce // DSP DMA Mem Address H
|
||||
#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
|
||||
|
||||
#define DSP_FORMAT 0xd1
|
||||
#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
|
||||
#define DSP_ACSAH 0xd4
|
||||
#define DSP_ACSAL 0xd5
|
||||
#define DSP_ACEAH 0xd6
|
||||
#define DSP_ACEAL 0xd7
|
||||
#define DSP_ACCAH 0xd8
|
||||
#define DSP_ACCAL 0xd9
|
||||
#define DSP_PRED_SCALE 0xda
|
||||
#define DSP_YN1 0xdb
|
||||
#define DSP_YN2 0xdc
|
||||
#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
|
||||
#define DSP_GAIN 0xde
|
||||
|
||||
#define DSP_DIRQ 0xfb // DSP Irq Rest
|
||||
#define DSP_DMBH 0xfc // DSP Mailbox H
|
||||
#define DSP_DMBL 0xfd // DSP Mailbox L
|
||||
#define DSP_CMBH 0xfe // CPU Mailbox H
|
||||
#define DSP_CMBL 0xff // CPU Mailbox L
|
||||
|
||||
#define DMA_TO_DSP 0
|
||||
#define DMA_TO_CPU 1
|
||||
|
||||
// Stacks
|
||||
#define DSP_STACK_C 0
|
||||
#define DSP_STACK_D 1
|
||||
|
||||
// cr (Not g_dsp.r[CR]) bits
|
||||
// See HW/DSP.cpp.
|
||||
#define CR_HALT 0x0004
|
||||
#define CR_EXTERNAL_INT 0x0002
|
||||
|
||||
|
||||
// SR bits
|
||||
#define SR_CARRY 0x0001
|
||||
#define SR_2 0x0002 // overflow???
|
||||
#define SR_ARITH_ZERO 0x0004
|
||||
#define SR_SIGN 0x0008
|
||||
#define SR_10 0x0010 // seem to be set by tst
|
||||
#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
|
||||
#define SR_LOGIC_ZERO 0x0040
|
||||
#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
|
||||
#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
|
||||
#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
|
||||
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
|
||||
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
|
||||
|
||||
// This should be the bits affected by CMP. Does not include logic zero.
|
||||
#define SR_CMP_MASK 0x3f
|
||||
|
||||
// exceptions vector
|
||||
#define EXP_RESET 0 // 0x0000
|
||||
#define EXP_STOVF 1 // 0x0002 stack under/over flow
|
||||
#define EXP_4 2 // 0x0004
|
||||
#define EXP_6 3 // 0x0006
|
||||
#define EXP_8 4 // 0x0008
|
||||
#define EXP_ACCOV 5 // 0x000a accelerator address overflow
|
||||
#define EXP_c 6 // 0x000c
|
||||
#define EXP_INT 7 // 0x000e external int? (mail?)
|
||||
|
||||
struct SDSP
|
||||
{
|
||||
u16 r[32];
|
||||
u16 pc;
|
||||
#if PROFILE
|
||||
u16 err_pc;
|
||||
#endif
|
||||
|
||||
// This is NOT the same cr as r[DSP_REG_CR].
|
||||
// This register is shared with the main emulation, see DSP.cpp
|
||||
// The plugin has control over 0x0C07 of this reg.
|
||||
// Bits are defined in a struct in DSP.cpp.
|
||||
u16 cr;
|
||||
|
||||
u8 reg_stack_ptr[4];
|
||||
u8 exceptions; // pending exceptions?
|
||||
bool exception_in_progress_hack; // is this the same as "exception enabled"?
|
||||
|
||||
// Let's make stack depth 32 for now. The real DSP has different depths
|
||||
// for the different stacks, but it would be strange if any ucode relied on stack
|
||||
// overflows since on the DSP, when the stack overflows, you're screwed.
|
||||
u16 reg_stack[4][DSP_STACK_DEPTH];
|
||||
|
||||
// For debugging.
|
||||
u32 iram_crc;
|
||||
u64 step_counter;
|
||||
|
||||
// When state saving, all of the above can just be memcpy'd into the save state.
|
||||
// The below needs special handling.
|
||||
u16 *iram;
|
||||
u16 *dram;
|
||||
u16 *irom;
|
||||
u16 *coef;
|
||||
|
||||
// This one doesn't really belong here.
|
||||
u8 *cpu_ram;
|
||||
};
|
||||
|
||||
extern SDSP g_dsp;
|
||||
extern DSPBreakpoints dsp_breakpoints;
|
||||
|
||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
|
||||
|
||||
void DSPCore_Reset();
|
||||
void DSPCore_Shutdown(); // Frees all allocated memory.
|
||||
|
||||
void DSPCore_CheckExternalInterrupt();
|
||||
void DSPCore_CheckExceptions();
|
||||
|
||||
// sets a flag in the pending exception register.
|
||||
void DSPCore_SetException(u8 level);
|
||||
|
||||
enum DSPCoreState
|
||||
{
|
||||
DSPCORE_RUNNING = 0,
|
||||
DSPCORE_STEPPING = 1,
|
||||
};
|
||||
|
||||
int DSPCore_RunCycles(int cycles);
|
||||
|
||||
// These are meant to be called from the UI thread.
|
||||
void DSPCore_SetState(DSPCoreState new_state);
|
||||
DSPCoreState DSPCore_GetState();
|
||||
|
||||
void DSPCore_Step();
|
||||
|
||||
#endif // _DSPCORE_H
|
||||
/*====================================================================
|
||||
|
||||
filename: DSPCore.h
|
||||
project: GCemu
|
||||
created: 2004-6-18
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie & Tratax
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#ifndef _DSPCORE_H
|
||||
#define _DSPCORE_H
|
||||
|
||||
#include "DSPBreakpoints.h"
|
||||
|
||||
#define DSP_IRAM_BYTE_SIZE 0x2000
|
||||
#define DSP_IRAM_SIZE 0x1000
|
||||
#define DSP_IRAM_MASK 0x0fff
|
||||
|
||||
#define DSP_IROM_BYTE_SIZE 0x2000
|
||||
#define DSP_IROM_SIZE 0x1000
|
||||
#define DSP_IROM_MASK 0x0fff
|
||||
|
||||
#define DSP_DRAM_BYTE_SIZE 0x2000
|
||||
#define DSP_DRAM_SIZE 0x1000
|
||||
#define DSP_DRAM_MASK 0x0fff
|
||||
|
||||
#define DSP_COEF_BYTE_SIZE 0x2000
|
||||
#define DSP_COEF_SIZE 0x1000
|
||||
#define DSP_COEF_MASK 0x0fff
|
||||
|
||||
#define DSP_RESET_VECTOR 0x8000
|
||||
|
||||
#define DSP_STACK_DEPTH 0x20
|
||||
#define DSP_STACK_MASK 0x1f
|
||||
|
||||
#define DSP_CR_IMEM 2
|
||||
#define DSP_CR_DMEM 0
|
||||
#define DSP_CR_TO_CPU 1
|
||||
#define DSP_CR_FROM_CPU 0
|
||||
|
||||
|
||||
// Register table taken from libasnd
|
||||
#define DSP_REG_AR0 0x00 // address registers
|
||||
#define DSP_REG_AR1 0x01
|
||||
#define DSP_REG_AR2 0x02
|
||||
#define DSP_REG_AR3 0x03
|
||||
|
||||
#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
|
||||
#define DSP_REG_IX1 0x05
|
||||
#define DSP_REG_IX2 0x06
|
||||
#define DSP_REG_IX3 0x07
|
||||
|
||||
#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
|
||||
#define DSP_REG_WR1 0x09
|
||||
#define DSP_REG_WR2 0x0a
|
||||
#define DSP_REG_WR3 0x0b
|
||||
|
||||
#define DSP_REG_ST0 0x0c // stacks.
|
||||
#define DSP_REG_ST1 0x0d
|
||||
#define DSP_REG_ST2 0x0e
|
||||
#define DSP_REG_ST3 0x0f
|
||||
|
||||
#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
|
||||
#define DSP_REG_SR 0x13
|
||||
|
||||
#define DSP_REG_PRODL 0x14 // product.
|
||||
#define DSP_REG_PRODM 0x15
|
||||
#define DSP_REG_PRODH 0x16
|
||||
#define DSP_REG_PRODM2 0x17
|
||||
|
||||
#define DSP_REG_AXL0 0x18
|
||||
#define DSP_REG_AXL1 0x19
|
||||
#define DSP_REG_AXH0 0x1a
|
||||
#define DSP_REG_AXH1 0x1b
|
||||
|
||||
#define DSP_REG_ACC0 0x1c // accumulator (global)
|
||||
#define DSP_REG_ACC1 0x1d
|
||||
|
||||
#define DSP_REG_ACL0 0x1c // Low accumulator
|
||||
#define DSP_REG_ACL1 0x1d
|
||||
#define DSP_REG_ACM0 0x1e // Mid accumulator
|
||||
#define DSP_REG_ACM1 0x1f
|
||||
#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
|
||||
#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
|
||||
|
||||
// Hardware registers address
|
||||
|
||||
#define DSP_COEF_A1_0 0xa0
|
||||
|
||||
#define DSP_DSMAH 0xce
|
||||
#define DSP_DSMAL 0xcf
|
||||
#define DSP_DSCR 0xc9 // DSP DMA Control Reg
|
||||
#define DSP_DSPA 0xcd // DSP DMA Block Length
|
||||
#define DSP_DSBL 0xcb // DSP DMA DMEM Address
|
||||
#define DSP_DSMAH 0xce // DSP DMA Mem Address H
|
||||
#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
|
||||
|
||||
#define DSP_FORMAT 0xd1
|
||||
#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
|
||||
#define DSP_ACSAH 0xd4
|
||||
#define DSP_ACSAL 0xd5
|
||||
#define DSP_ACEAH 0xd6
|
||||
#define DSP_ACEAL 0xd7
|
||||
#define DSP_ACCAH 0xd8
|
||||
#define DSP_ACCAL 0xd9
|
||||
#define DSP_PRED_SCALE 0xda
|
||||
#define DSP_YN1 0xdb
|
||||
#define DSP_YN2 0xdc
|
||||
#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
|
||||
#define DSP_GAIN 0xde
|
||||
|
||||
#define DSP_DIRQ 0xfb // DSP Irq Rest
|
||||
#define DSP_DMBH 0xfc // DSP Mailbox H
|
||||
#define DSP_DMBL 0xfd // DSP Mailbox L
|
||||
#define DSP_CMBH 0xfe // CPU Mailbox H
|
||||
#define DSP_CMBL 0xff // CPU Mailbox L
|
||||
|
||||
#define DMA_TO_DSP 0
|
||||
#define DMA_TO_CPU 1
|
||||
|
||||
// Stacks
|
||||
#define DSP_STACK_C 0
|
||||
#define DSP_STACK_D 1
|
||||
|
||||
// cr (Not g_dsp.r[CR]) bits
|
||||
// See HW/DSP.cpp.
|
||||
#define CR_HALT 0x0004
|
||||
#define CR_EXTERNAL_INT 0x0002
|
||||
|
||||
|
||||
// SR bits
|
||||
#define SR_CARRY 0x0001
|
||||
#define SR_2 0x0002 // overflow???
|
||||
#define SR_ARITH_ZERO 0x0004
|
||||
#define SR_SIGN 0x0008
|
||||
#define SR_10 0x0010 // seem to be set by tst
|
||||
#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
|
||||
#define SR_LOGIC_ZERO 0x0040
|
||||
#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
|
||||
#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
|
||||
#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
|
||||
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
|
||||
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
|
||||
|
||||
// This should be the bits affected by CMP. Does not include logic zero.
|
||||
#define SR_CMP_MASK 0x3f
|
||||
|
||||
// exceptions vector
|
||||
#define EXP_RESET 0 // 0x0000
|
||||
#define EXP_STOVF 1 // 0x0002 stack under/over flow
|
||||
#define EXP_4 2 // 0x0004
|
||||
#define EXP_6 3 // 0x0006
|
||||
#define EXP_8 4 // 0x0008
|
||||
#define EXP_ACCOV 5 // 0x000a accelerator address overflow
|
||||
#define EXP_c 6 // 0x000c
|
||||
#define EXP_INT 7 // 0x000e external int? (mail?)
|
||||
|
||||
struct SDSP
|
||||
{
|
||||
u16 r[32];
|
||||
u16 pc;
|
||||
#if PROFILE
|
||||
u16 err_pc;
|
||||
#endif
|
||||
|
||||
// This is NOT the same cr as r[DSP_REG_CR].
|
||||
// This register is shared with the main emulation, see DSP.cpp
|
||||
// The plugin has control over 0x0C07 of this reg.
|
||||
// Bits are defined in a struct in DSP.cpp.
|
||||
u16 cr;
|
||||
|
||||
u8 reg_stack_ptr[4];
|
||||
u8 exceptions; // pending exceptions?
|
||||
bool exception_in_progress_hack; // is this the same as "exception enabled"?
|
||||
|
||||
// Let's make stack depth 32 for now. The real DSP has different depths
|
||||
// for the different stacks, but it would be strange if any ucode relied on stack
|
||||
// overflows since on the DSP, when the stack overflows, you're screwed.
|
||||
u16 reg_stack[4][DSP_STACK_DEPTH];
|
||||
|
||||
// For debugging.
|
||||
u32 iram_crc;
|
||||
u64 step_counter;
|
||||
|
||||
// When state saving, all of the above can just be memcpy'd into the save state.
|
||||
// The below needs special handling.
|
||||
u16 *iram;
|
||||
u16 *dram;
|
||||
u16 *irom;
|
||||
u16 *coef;
|
||||
|
||||
// This one doesn't really belong here.
|
||||
u8 *cpu_ram;
|
||||
};
|
||||
|
||||
extern SDSP g_dsp;
|
||||
extern DSPBreakpoints dsp_breakpoints;
|
||||
|
||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
|
||||
|
||||
void DSPCore_Reset();
|
||||
void DSPCore_Shutdown(); // Frees all allocated memory.
|
||||
|
||||
void DSPCore_CheckExternalInterrupt();
|
||||
void DSPCore_CheckExceptions();
|
||||
|
||||
// sets a flag in the pending exception register.
|
||||
void DSPCore_SetException(u8 level);
|
||||
|
||||
enum DSPCoreState
|
||||
{
|
||||
DSPCORE_RUNNING = 0,
|
||||
DSPCORE_STEPPING = 1,
|
||||
};
|
||||
|
||||
int DSPCore_RunCycles(int cycles);
|
||||
|
||||
// These are meant to be called from the UI thread.
|
||||
void DSPCore_SetState(DSPCoreState new_state);
|
||||
DSPCoreState DSPCore_GetState();
|
||||
|
||||
void DSPCore_Step();
|
||||
|
||||
#endif // _DSPCORE_H
|
||||
|
@ -1,35 +1,35 @@
|
||||
// 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/
|
||||
|
||||
#ifndef _DSPHOST_H
|
||||
#define _DSPHOST_H
|
||||
|
||||
// The user of the DSPCore library must supply a few functions so that the
|
||||
// emulation core can access the environment it runs in. If the emulation
|
||||
// core isn't used, for example in an asm/disasm tool, then most of these
|
||||
// can be stubbed out.
|
||||
#define DEBUG_EXP 1
|
||||
|
||||
u8 DSPHost_ReadHostMemory(u32 addr);
|
||||
void DSPHost_WriteHostMemory(u8 value, u32 addr);
|
||||
bool DSPHost_OnThread();
|
||||
bool DSPHost_Running();
|
||||
void DSPHost_InterruptRequest();
|
||||
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
|
||||
void DSPHost_UpdateDebugger();
|
||||
|
||||
#endif
|
||||
// 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/
|
||||
|
||||
#ifndef _DSPHOST_H
|
||||
#define _DSPHOST_H
|
||||
|
||||
// The user of the DSPCore library must supply a few functions so that the
|
||||
// emulation core can access the environment it runs in. If the emulation
|
||||
// core isn't used, for example in an asm/disasm tool, then most of these
|
||||
// can be stubbed out.
|
||||
#define DEBUG_EXP 1
|
||||
|
||||
u8 DSPHost_ReadHostMemory(u32 addr);
|
||||
void DSPHost_WriteHostMemory(u8 value, u32 addr);
|
||||
bool DSPHost_OnThread();
|
||||
bool DSPHost_Running();
|
||||
void DSPHost_InterruptRequest();
|
||||
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
|
||||
void DSPHost_UpdateDebugger();
|
||||
|
||||
#endif
|
||||
|
@ -1,140 +1,140 @@
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
|
||||
#include "DSPIntCCUtil.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void Update_SR_Register64(s64 _Value)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
if (_Value < 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
}
|
||||
|
||||
if (_Value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
}
|
||||
|
||||
// weird
|
||||
if ((_Value >> 62) == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
void Update_SR_Register16(s16 _Value)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
if (_Value < 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
}
|
||||
|
||||
if (_Value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
}
|
||||
|
||||
// weird
|
||||
if ((_Value >> 14) == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
void Update_SR_LZ(s64 value) {
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetMultiplyModifier()
|
||||
{
|
||||
if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
inline bool isCarry() {
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
|
||||
}
|
||||
inline bool isSign() {
|
||||
return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
|
||||
}
|
||||
inline bool isZero() {
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
|
||||
}
|
||||
|
||||
//see gdsp_registers.h for flags
|
||||
bool CheckCondition(u8 _Condition)
|
||||
{
|
||||
switch (_Condition & 0xf)
|
||||
{
|
||||
case 0x0: //NS - NOT SIGN
|
||||
return !isSign();
|
||||
case 0x1: // S - SIGN
|
||||
return isSign();
|
||||
case 0x2: // G - GREATER
|
||||
return !isSign() && !isZero();
|
||||
case 0x3: // LE - LESS EQUAL
|
||||
return isSign() || isZero();
|
||||
case 0x4: // NZ - NOT ZERO
|
||||
return !isZero();
|
||||
case 0x5: // Z - ZERO
|
||||
return isZero();
|
||||
case 0x6: // L - LESS
|
||||
// Should be that once we set 0x01
|
||||
return !isCarry();
|
||||
// if (isSign())
|
||||
case 0x7: // GE - GREATER EQUAL
|
||||
// Should be that once we set 0x01
|
||||
return isCarry();
|
||||
// if (! isSign() || isZero())
|
||||
case 0xc: // LNZ - LOGIC NOT ZERO
|
||||
return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
|
||||
case 0xd: // LZ - LOGIC ZERO
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
|
||||
|
||||
case 0xf: // Empty - always true.
|
||||
return true;
|
||||
default:
|
||||
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
|
||||
#include "DSPIntCCUtil.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void Update_SR_Register64(s64 _Value)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
if (_Value < 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
}
|
||||
|
||||
if (_Value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
}
|
||||
|
||||
// weird
|
||||
if ((_Value >> 62) == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
void Update_SR_Register16(s16 _Value)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
if (_Value < 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
}
|
||||
|
||||
if (_Value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
}
|
||||
|
||||
// weird
|
||||
if ((_Value >> 14) == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
void Update_SR_LZ(s64 value) {
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetMultiplyModifier()
|
||||
{
|
||||
if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
inline bool isCarry() {
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
|
||||
}
|
||||
inline bool isSign() {
|
||||
return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
|
||||
}
|
||||
inline bool isZero() {
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
|
||||
}
|
||||
|
||||
//see gdsp_registers.h for flags
|
||||
bool CheckCondition(u8 _Condition)
|
||||
{
|
||||
switch (_Condition & 0xf)
|
||||
{
|
||||
case 0x0: //NS - NOT SIGN
|
||||
return !isSign();
|
||||
case 0x1: // S - SIGN
|
||||
return isSign();
|
||||
case 0x2: // G - GREATER
|
||||
return !isSign() && !isZero();
|
||||
case 0x3: // LE - LESS EQUAL
|
||||
return isSign() || isZero();
|
||||
case 0x4: // NZ - NOT ZERO
|
||||
return !isZero();
|
||||
case 0x5: // Z - ZERO
|
||||
return isZero();
|
||||
case 0x6: // L - LESS
|
||||
// Should be that once we set 0x01
|
||||
return !isCarry();
|
||||
// if (isSign())
|
||||
case 0x7: // GE - GREATER EQUAL
|
||||
// Should be that once we set 0x01
|
||||
return isCarry();
|
||||
// if (! isSign() || isZero())
|
||||
case 0xc: // LNZ - LOGIC NOT ZERO
|
||||
return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
|
||||
case 0xd: // LZ - LOGIC ZERO
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
|
||||
|
||||
case 0xf: // Empty - always true.
|
||||
return true;
|
||||
default:
|
||||
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1,39 +1,39 @@
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#ifndef _GDSP_CONDITION_CODES_H
|
||||
#define _GDSP_CONDITION_CODES_H
|
||||
|
||||
// Anything to do with SR and conditions goes here.
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
bool CheckCondition(u8 _Condition);
|
||||
|
||||
int GetMultiplyModifier();
|
||||
|
||||
void Update_SR_Register16(s16 _Value);
|
||||
void Update_SR_Register64(s64 _Value);
|
||||
void Update_SR_LZ(s64 value);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _GDSP_CONDITION_CODES_H
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#ifndef _GDSP_CONDITION_CODES_H
|
||||
#define _GDSP_CONDITION_CODES_H
|
||||
|
||||
// Anything to do with SR and conditions goes here.
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
bool CheckCondition(u8 _Condition);
|
||||
|
||||
int GetMultiplyModifier();
|
||||
|
||||
void Update_SR_Register16(s16 _Value);
|
||||
void Update_SR_Register64(s64 _Value);
|
||||
void Update_SR_LZ(s64 value);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _GDSP_CONDITION_CODES_H
|
||||
|
@ -1,171 +1,171 @@
|
||||
// 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/
|
||||
|
||||
#ifndef _DSPINTERPRETER_H
|
||||
#define _DSPINTERPRETER_H
|
||||
|
||||
#include "DSPTables.h"
|
||||
|
||||
#define DSP_REG_MASK 0x1f
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void Step();
|
||||
void Run();
|
||||
|
||||
// If these simply return the same number of cycles as was passed into them,
|
||||
// chances are that the DSP is halted.
|
||||
// The difference between them is that the debug one obeys breakpoints.
|
||||
int RunCycles(int cycles);
|
||||
int RunCyclesDebug(int cycles);
|
||||
|
||||
void Stop();
|
||||
|
||||
void WriteCR(u16 val);
|
||||
u16 ReadCR();
|
||||
|
||||
|
||||
typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
|
||||
|
||||
// All the opcode functions.
|
||||
void unknown(const UDSPInstruction& opc);
|
||||
void call(const UDSPInstruction& opc);
|
||||
void callr(const UDSPInstruction& opc);
|
||||
void ifcc(const UDSPInstruction& opc);
|
||||
void jcc(const UDSPInstruction& opc);
|
||||
void jmprcc(const UDSPInstruction& opc);
|
||||
void ret(const UDSPInstruction& opc);
|
||||
void halt(const UDSPInstruction& opc);
|
||||
void loop(const UDSPInstruction& opc);
|
||||
void loopi(const UDSPInstruction& opc);
|
||||
void bloop(const UDSPInstruction& opc);
|
||||
void bloopi(const UDSPInstruction& opc);
|
||||
void mrr(const UDSPInstruction& opc);
|
||||
void lrr(const UDSPInstruction& opc);
|
||||
void lrrd(const UDSPInstruction& opc);
|
||||
void lrri(const UDSPInstruction& opc);
|
||||
void lrrn(const UDSPInstruction& opc);
|
||||
void srr(const UDSPInstruction& opc);
|
||||
void srrd(const UDSPInstruction& opc);
|
||||
void srri(const UDSPInstruction& opc);
|
||||
void srrn(const UDSPInstruction& opc);
|
||||
void lri(const UDSPInstruction& opc);
|
||||
void lris(const UDSPInstruction& opc);
|
||||
void lr(const UDSPInstruction& opc);
|
||||
void sr(const UDSPInstruction& opc);
|
||||
void si(const UDSPInstruction& opc);
|
||||
void tstaxh(const UDSPInstruction& opc);
|
||||
void clr(const UDSPInstruction& opc);
|
||||
void clrl(const UDSPInstruction& opc);
|
||||
void clrp(const UDSPInstruction& opc);
|
||||
void mulc(const UDSPInstruction& opc);
|
||||
void cmpar(const UDSPInstruction& opc);
|
||||
void cmp(const UDSPInstruction& opc);
|
||||
void tst(const UDSPInstruction& opc);
|
||||
void addaxl(const UDSPInstruction& opc);
|
||||
void addarn(const UDSPInstruction& opc);
|
||||
void mulcac(const UDSPInstruction& opc);
|
||||
void movr(const UDSPInstruction& opc);
|
||||
void movax(const UDSPInstruction& opc);
|
||||
void xorr(const UDSPInstruction& opc);
|
||||
void andr(const UDSPInstruction& opc);
|
||||
void andc(const UDSPInstruction& opc);
|
||||
void orr(const UDSPInstruction& opc);
|
||||
void orc(const UDSPInstruction& opc);
|
||||
void orf(const UDSPInstruction& opc);
|
||||
void add(const UDSPInstruction& opc);
|
||||
void addp(const UDSPInstruction& opc);
|
||||
void cmpis(const UDSPInstruction& opc);
|
||||
void addpaxz(const UDSPInstruction& opc);
|
||||
void movpz(const UDSPInstruction& opc);
|
||||
void decm(const UDSPInstruction& opc);
|
||||
void dec(const UDSPInstruction& opc);
|
||||
void inc(const UDSPInstruction& opc);
|
||||
void incm(const UDSPInstruction& opc);
|
||||
void neg(const UDSPInstruction& opc);
|
||||
void addax(const UDSPInstruction& opc);
|
||||
void addr(const UDSPInstruction& opc);
|
||||
void subr(const UDSPInstruction& opc);
|
||||
void subp(const UDSPInstruction& opc);
|
||||
void subax(const UDSPInstruction& opc);
|
||||
void addis(const UDSPInstruction& opc);
|
||||
void addi(const UDSPInstruction& opc);
|
||||
void lsl16(const UDSPInstruction& opc);
|
||||
void madd(const UDSPInstruction& opc);
|
||||
void msub(const UDSPInstruction& opc);
|
||||
void lsr16(const UDSPInstruction& opc);
|
||||
void asr16(const UDSPInstruction& opc);
|
||||
void lsl(const UDSPInstruction& opc);
|
||||
void lsr(const UDSPInstruction& opc);
|
||||
void asl(const UDSPInstruction& opc);
|
||||
void asr(const UDSPInstruction& opc);
|
||||
void lsrn(const UDSPInstruction& opc);
|
||||
void asrn(const UDSPInstruction& opc);
|
||||
void dar(const UDSPInstruction& opc);
|
||||
void iar(const UDSPInstruction& opc);
|
||||
void sbclr(const UDSPInstruction& opc);
|
||||
void sbset(const UDSPInstruction& opc);
|
||||
void mov(const UDSPInstruction& opc);
|
||||
void movp(const UDSPInstruction& opc);
|
||||
void mul(const UDSPInstruction& opc);
|
||||
void mulac(const UDSPInstruction& opc);
|
||||
void mulmv(const UDSPInstruction& opc);
|
||||
void mulmvz(const UDSPInstruction& opc);
|
||||
void mulx(const UDSPInstruction& opc);
|
||||
void mulxac(const UDSPInstruction& opc);
|
||||
void mulxmv(const UDSPInstruction& opc);
|
||||
void mulxmvz(const UDSPInstruction& opc);
|
||||
void mulcmvz(const UDSPInstruction& opc);
|
||||
void mulcmv(const UDSPInstruction& opc);
|
||||
void movnp(const UDSPInstruction& opc);
|
||||
void sub(const UDSPInstruction& opc);
|
||||
void maddx(const UDSPInstruction& opc);
|
||||
void msubx(const UDSPInstruction& opc);
|
||||
void maddc(const UDSPInstruction& opc);
|
||||
void msubc(const UDSPInstruction& opc);
|
||||
void srs(const UDSPInstruction& opc);
|
||||
void lrs(const UDSPInstruction& opc);
|
||||
void nx(const UDSPInstruction& opc);
|
||||
void cmpi(const UDSPInstruction& opc);
|
||||
void rti(const UDSPInstruction& opc);
|
||||
void ilrr(const UDSPInstruction& opc);
|
||||
void ilrrd(const UDSPInstruction& opc);
|
||||
void ilrri(const UDSPInstruction& opc);
|
||||
void ilrrn(const UDSPInstruction& opc);
|
||||
void andcf(const UDSPInstruction& opc);
|
||||
void andf(const UDSPInstruction& opc);
|
||||
void xori(const UDSPInstruction& opc);
|
||||
void andi(const UDSPInstruction& opc);
|
||||
void ori(const UDSPInstruction& opc);
|
||||
|
||||
// FIXME inside
|
||||
void srbith(const UDSPInstruction& opc);
|
||||
|
||||
// END OF FIXMEs
|
||||
|
||||
// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
|
||||
void tstaxl(const UDSPInstruction& opc);
|
||||
// The mysterious a100
|
||||
|
||||
// END OF UNIMPLEMENTED
|
||||
|
||||
// Helpers
|
||||
inline void tsta(int reg);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _DSPINTERPRETER_H
|
||||
// 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/
|
||||
|
||||
#ifndef _DSPINTERPRETER_H
|
||||
#define _DSPINTERPRETER_H
|
||||
|
||||
#include "DSPTables.h"
|
||||
|
||||
#define DSP_REG_MASK 0x1f
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void Step();
|
||||
void Run();
|
||||
|
||||
// If these simply return the same number of cycles as was passed into them,
|
||||
// chances are that the DSP is halted.
|
||||
// The difference between them is that the debug one obeys breakpoints.
|
||||
int RunCycles(int cycles);
|
||||
int RunCyclesDebug(int cycles);
|
||||
|
||||
void Stop();
|
||||
|
||||
void WriteCR(u16 val);
|
||||
u16 ReadCR();
|
||||
|
||||
|
||||
typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
|
||||
|
||||
// All the opcode functions.
|
||||
void unknown(const UDSPInstruction& opc);
|
||||
void call(const UDSPInstruction& opc);
|
||||
void callr(const UDSPInstruction& opc);
|
||||
void ifcc(const UDSPInstruction& opc);
|
||||
void jcc(const UDSPInstruction& opc);
|
||||
void jmprcc(const UDSPInstruction& opc);
|
||||
void ret(const UDSPInstruction& opc);
|
||||
void halt(const UDSPInstruction& opc);
|
||||
void loop(const UDSPInstruction& opc);
|
||||
void loopi(const UDSPInstruction& opc);
|
||||
void bloop(const UDSPInstruction& opc);
|
||||
void bloopi(const UDSPInstruction& opc);
|
||||
void mrr(const UDSPInstruction& opc);
|
||||
void lrr(const UDSPInstruction& opc);
|
||||
void lrrd(const UDSPInstruction& opc);
|
||||
void lrri(const UDSPInstruction& opc);
|
||||
void lrrn(const UDSPInstruction& opc);
|
||||
void srr(const UDSPInstruction& opc);
|
||||
void srrd(const UDSPInstruction& opc);
|
||||
void srri(const UDSPInstruction& opc);
|
||||
void srrn(const UDSPInstruction& opc);
|
||||
void lri(const UDSPInstruction& opc);
|
||||
void lris(const UDSPInstruction& opc);
|
||||
void lr(const UDSPInstruction& opc);
|
||||
void sr(const UDSPInstruction& opc);
|
||||
void si(const UDSPInstruction& opc);
|
||||
void tstaxh(const UDSPInstruction& opc);
|
||||
void clr(const UDSPInstruction& opc);
|
||||
void clrl(const UDSPInstruction& opc);
|
||||
void clrp(const UDSPInstruction& opc);
|
||||
void mulc(const UDSPInstruction& opc);
|
||||
void cmpar(const UDSPInstruction& opc);
|
||||
void cmp(const UDSPInstruction& opc);
|
||||
void tst(const UDSPInstruction& opc);
|
||||
void addaxl(const UDSPInstruction& opc);
|
||||
void addarn(const UDSPInstruction& opc);
|
||||
void mulcac(const UDSPInstruction& opc);
|
||||
void movr(const UDSPInstruction& opc);
|
||||
void movax(const UDSPInstruction& opc);
|
||||
void xorr(const UDSPInstruction& opc);
|
||||
void andr(const UDSPInstruction& opc);
|
||||
void andc(const UDSPInstruction& opc);
|
||||
void orr(const UDSPInstruction& opc);
|
||||
void orc(const UDSPInstruction& opc);
|
||||
void orf(const UDSPInstruction& opc);
|
||||
void add(const UDSPInstruction& opc);
|
||||
void addp(const UDSPInstruction& opc);
|
||||
void cmpis(const UDSPInstruction& opc);
|
||||
void addpaxz(const UDSPInstruction& opc);
|
||||
void movpz(const UDSPInstruction& opc);
|
||||
void decm(const UDSPInstruction& opc);
|
||||
void dec(const UDSPInstruction& opc);
|
||||
void inc(const UDSPInstruction& opc);
|
||||
void incm(const UDSPInstruction& opc);
|
||||
void neg(const UDSPInstruction& opc);
|
||||
void addax(const UDSPInstruction& opc);
|
||||
void addr(const UDSPInstruction& opc);
|
||||
void subr(const UDSPInstruction& opc);
|
||||
void subp(const UDSPInstruction& opc);
|
||||
void subax(const UDSPInstruction& opc);
|
||||
void addis(const UDSPInstruction& opc);
|
||||
void addi(const UDSPInstruction& opc);
|
||||
void lsl16(const UDSPInstruction& opc);
|
||||
void madd(const UDSPInstruction& opc);
|
||||
void msub(const UDSPInstruction& opc);
|
||||
void lsr16(const UDSPInstruction& opc);
|
||||
void asr16(const UDSPInstruction& opc);
|
||||
void lsl(const UDSPInstruction& opc);
|
||||
void lsr(const UDSPInstruction& opc);
|
||||
void asl(const UDSPInstruction& opc);
|
||||
void asr(const UDSPInstruction& opc);
|
||||
void lsrn(const UDSPInstruction& opc);
|
||||
void asrn(const UDSPInstruction& opc);
|
||||
void dar(const UDSPInstruction& opc);
|
||||
void iar(const UDSPInstruction& opc);
|
||||
void sbclr(const UDSPInstruction& opc);
|
||||
void sbset(const UDSPInstruction& opc);
|
||||
void mov(const UDSPInstruction& opc);
|
||||
void movp(const UDSPInstruction& opc);
|
||||
void mul(const UDSPInstruction& opc);
|
||||
void mulac(const UDSPInstruction& opc);
|
||||
void mulmv(const UDSPInstruction& opc);
|
||||
void mulmvz(const UDSPInstruction& opc);
|
||||
void mulx(const UDSPInstruction& opc);
|
||||
void mulxac(const UDSPInstruction& opc);
|
||||
void mulxmv(const UDSPInstruction& opc);
|
||||
void mulxmvz(const UDSPInstruction& opc);
|
||||
void mulcmvz(const UDSPInstruction& opc);
|
||||
void mulcmv(const UDSPInstruction& opc);
|
||||
void movnp(const UDSPInstruction& opc);
|
||||
void sub(const UDSPInstruction& opc);
|
||||
void maddx(const UDSPInstruction& opc);
|
||||
void msubx(const UDSPInstruction& opc);
|
||||
void maddc(const UDSPInstruction& opc);
|
||||
void msubc(const UDSPInstruction& opc);
|
||||
void srs(const UDSPInstruction& opc);
|
||||
void lrs(const UDSPInstruction& opc);
|
||||
void nx(const UDSPInstruction& opc);
|
||||
void cmpi(const UDSPInstruction& opc);
|
||||
void rti(const UDSPInstruction& opc);
|
||||
void ilrr(const UDSPInstruction& opc);
|
||||
void ilrrd(const UDSPInstruction& opc);
|
||||
void ilrri(const UDSPInstruction& opc);
|
||||
void ilrrn(const UDSPInstruction& opc);
|
||||
void andcf(const UDSPInstruction& opc);
|
||||
void andf(const UDSPInstruction& opc);
|
||||
void xori(const UDSPInstruction& opc);
|
||||
void andi(const UDSPInstruction& opc);
|
||||
void ori(const UDSPInstruction& opc);
|
||||
|
||||
// FIXME inside
|
||||
void srbith(const UDSPInstruction& opc);
|
||||
|
||||
// END OF FIXMEs
|
||||
|
||||
// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
|
||||
void tstaxl(const UDSPInstruction& opc);
|
||||
// The mysterious a100
|
||||
|
||||
// END OF UNIMPLEMENTED
|
||||
|
||||
// Helpers
|
||||
inline void tsta(int reg);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _DSPINTERPRETER_H
|
||||
|
@ -1,22 +1,22 @@
|
||||
// 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 "DSPJit.h"
|
||||
|
||||
namespace DSPJit {
|
||||
|
||||
};
|
||||
// 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 "DSPJit.h"
|
||||
|
||||
namespace DSPJit {
|
||||
|
||||
};
|
||||
|
@ -1,28 +1,28 @@
|
||||
// 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/
|
||||
|
||||
#ifndef _DSPJIT_H
|
||||
#define _DSPJIT_H
|
||||
|
||||
namespace DSPJit {
|
||||
|
||||
// TODO(XK): Fill
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _DSPJIT_H
|
||||
// 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/
|
||||
|
||||
#ifndef _DSPJIT_H
|
||||
#define _DSPJIT_H
|
||||
|
||||
namespace DSPJit {
|
||||
|
||||
// TODO(XK): Fill
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _DSPJIT_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,168 +1,168 @@
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
|
||||
|
||||
#ifndef _DSPTABLES_H
|
||||
#define _DSPTABLES_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// The non-ADDR ones that end with _D are the opposite one - if the bit specify
|
||||
// ACC0, then ACC_D will be ACC1.
|
||||
|
||||
// The values of these are very important.
|
||||
// For the reg ones, the value >> 8 is the base register.
|
||||
// & 0x80 means it's a "D".
|
||||
|
||||
enum partype_t
|
||||
{
|
||||
P_NONE = 0x0000,
|
||||
P_VAL = 0x0001,
|
||||
P_IMM = 0x0002,
|
||||
P_MEM = 0x0003,
|
||||
P_STR = 0x0004,
|
||||
P_ADDR_I = 0x0005,
|
||||
P_ADDR_D = 0x0006,
|
||||
P_REG = 0x8000,
|
||||
P_REG04 = P_REG | 0x0400, // IX
|
||||
P_REG08 = P_REG | 0x0800,
|
||||
P_REG18 = P_REG | 0x1800,
|
||||
P_REGM18 = P_REG | 0x1810, // used in multiply instructions
|
||||
P_REG19 = P_REG | 0x1900,
|
||||
P_REGM19 = P_REG | 0x1910, // used in multiply instructions
|
||||
P_REG1A = P_REG | 0x1a80,
|
||||
P_REG1C = P_REG | 0x1c00,
|
||||
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
|
||||
P_ACC_D = P_REG | 0x1c80,
|
||||
P_ACCL = P_REG | 0x1c00, // used for low part of accum
|
||||
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
|
||||
// The following are not in gcdsptool
|
||||
P_ACCM_D = P_REG | 0x1e80,
|
||||
P_ACC = P_REG | 0x2000, // used for full accum.
|
||||
P_AX = P_REG | 0x2200,
|
||||
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
|
||||
P_REF = P_REG | 0x4000,
|
||||
P_PRG = P_REF | P_REG,
|
||||
|
||||
// The following seem like junk:
|
||||
// P_REG10 = P_REG | 0x1000,
|
||||
// P_AX_D = P_REG | 0x2280,
|
||||
};
|
||||
|
||||
#define P_EXT 0x80
|
||||
|
||||
#define OPTABLE_SIZE 65536
|
||||
|
||||
union UDSPInstruction
|
||||
{
|
||||
u16 hex;
|
||||
|
||||
UDSPInstruction(u16 _hex) { hex = _hex; }
|
||||
UDSPInstruction() { hex = 0; }
|
||||
|
||||
struct
|
||||
{
|
||||
signed shift : 6;
|
||||
unsigned negating : 1;
|
||||
unsigned arithmetic : 1;
|
||||
unsigned areg : 1;
|
||||
unsigned op : 7;
|
||||
};
|
||||
struct
|
||||
{
|
||||
unsigned ushift : 6;
|
||||
};
|
||||
|
||||
// TODO: Figure out more instruction structures (add structs here)
|
||||
};
|
||||
|
||||
typedef void (*dspInstFunc)(const UDSPInstruction&);
|
||||
|
||||
struct param2_t
|
||||
{
|
||||
partype_t type;
|
||||
u8 size;
|
||||
u8 loc;
|
||||
s8 lshift;
|
||||
u16 mask;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
u16 opcode;
|
||||
u16 opcode_mask;
|
||||
|
||||
dspInstFunc interpFunc;
|
||||
dspInstFunc jitFunc;
|
||||
|
||||
u8 size;
|
||||
u8 param_count;
|
||||
param2_t params[8];
|
||||
dspInstFunc prologue;
|
||||
dspInstFunc epilogue;
|
||||
} DSPOPCTemplate;
|
||||
|
||||
typedef DSPOPCTemplate opc_t;
|
||||
|
||||
// Opcodes
|
||||
extern const DSPOPCTemplate opcodes[];
|
||||
extern const int opcodes_size;
|
||||
extern const DSPOPCTemplate opcodes_ext[];
|
||||
extern const int opcodes_ext_size;
|
||||
extern u8 opSize[OPTABLE_SIZE];
|
||||
extern const DSPOPCTemplate cw;
|
||||
|
||||
extern dspInstFunc opTable[];
|
||||
extern dspInstFunc prologueTable[OPTABLE_SIZE];
|
||||
extern dspInstFunc epilogueTable[OPTABLE_SIZE];
|
||||
|
||||
// Predefined labels
|
||||
struct pdlabel_t
|
||||
{
|
||||
u16 addr;
|
||||
const char* name;
|
||||
const char* description;
|
||||
};
|
||||
|
||||
extern const pdlabel_t regnames[];
|
||||
extern const pdlabel_t pdlabels[];
|
||||
extern const u32 pdlabels_size;
|
||||
|
||||
const char *pdname(u16 val);
|
||||
const char *pdregname(int val);
|
||||
const char *pdregnamelong(int val);
|
||||
|
||||
void InitInstructionTable();
|
||||
|
||||
inline void ExecuteInstruction(const UDSPInstruction& inst)
|
||||
{
|
||||
// TODO: Move the prologuetable calls into the relevant instructions themselves.
|
||||
// Better not do things like this until things work correctly though.
|
||||
if (prologueTable[inst.hex])
|
||||
prologueTable[inst.hex](inst);
|
||||
opTable[inst.hex](inst);
|
||||
if (epilogueTable[inst.hex])
|
||||
epilogueTable[inst.hex](inst);
|
||||
}
|
||||
|
||||
// This one's pretty slow, try to use it only at init or seldomly.
|
||||
// returns NULL if no matching instruction.
|
||||
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
|
||||
|
||||
#endif // _DSPTABLES_H
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
|
||||
|
||||
#ifndef _DSPTABLES_H
|
||||
#define _DSPTABLES_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// The non-ADDR ones that end with _D are the opposite one - if the bit specify
|
||||
// ACC0, then ACC_D will be ACC1.
|
||||
|
||||
// The values of these are very important.
|
||||
// For the reg ones, the value >> 8 is the base register.
|
||||
// & 0x80 means it's a "D".
|
||||
|
||||
enum partype_t
|
||||
{
|
||||
P_NONE = 0x0000,
|
||||
P_VAL = 0x0001,
|
||||
P_IMM = 0x0002,
|
||||
P_MEM = 0x0003,
|
||||
P_STR = 0x0004,
|
||||
P_ADDR_I = 0x0005,
|
||||
P_ADDR_D = 0x0006,
|
||||
P_REG = 0x8000,
|
||||
P_REG04 = P_REG | 0x0400, // IX
|
||||
P_REG08 = P_REG | 0x0800,
|
||||
P_REG18 = P_REG | 0x1800,
|
||||
P_REGM18 = P_REG | 0x1810, // used in multiply instructions
|
||||
P_REG19 = P_REG | 0x1900,
|
||||
P_REGM19 = P_REG | 0x1910, // used in multiply instructions
|
||||
P_REG1A = P_REG | 0x1a80,
|
||||
P_REG1C = P_REG | 0x1c00,
|
||||
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
|
||||
P_ACC_D = P_REG | 0x1c80,
|
||||
P_ACCL = P_REG | 0x1c00, // used for low part of accum
|
||||
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
|
||||
// The following are not in gcdsptool
|
||||
P_ACCM_D = P_REG | 0x1e80,
|
||||
P_ACC = P_REG | 0x2000, // used for full accum.
|
||||
P_AX = P_REG | 0x2200,
|
||||
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
|
||||
P_REF = P_REG | 0x4000,
|
||||
P_PRG = P_REF | P_REG,
|
||||
|
||||
// The following seem like junk:
|
||||
// P_REG10 = P_REG | 0x1000,
|
||||
// P_AX_D = P_REG | 0x2280,
|
||||
};
|
||||
|
||||
#define P_EXT 0x80
|
||||
|
||||
#define OPTABLE_SIZE 65536
|
||||
|
||||
union UDSPInstruction
|
||||
{
|
||||
u16 hex;
|
||||
|
||||
UDSPInstruction(u16 _hex) { hex = _hex; }
|
||||
UDSPInstruction() { hex = 0; }
|
||||
|
||||
struct
|
||||
{
|
||||
signed shift : 6;
|
||||
unsigned negating : 1;
|
||||
unsigned arithmetic : 1;
|
||||
unsigned areg : 1;
|
||||
unsigned op : 7;
|
||||
};
|
||||
struct
|
||||
{
|
||||
unsigned ushift : 6;
|
||||
};
|
||||
|
||||
// TODO: Figure out more instruction structures (add structs here)
|
||||
};
|
||||
|
||||
typedef void (*dspInstFunc)(const UDSPInstruction&);
|
||||
|
||||
struct param2_t
|
||||
{
|
||||
partype_t type;
|
||||
u8 size;
|
||||
u8 loc;
|
||||
s8 lshift;
|
||||
u16 mask;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
u16 opcode;
|
||||
u16 opcode_mask;
|
||||
|
||||
dspInstFunc interpFunc;
|
||||
dspInstFunc jitFunc;
|
||||
|
||||
u8 size;
|
||||
u8 param_count;
|
||||
param2_t params[8];
|
||||
dspInstFunc prologue;
|
||||
dspInstFunc epilogue;
|
||||
} DSPOPCTemplate;
|
||||
|
||||
typedef DSPOPCTemplate opc_t;
|
||||
|
||||
// Opcodes
|
||||
extern const DSPOPCTemplate opcodes[];
|
||||
extern const int opcodes_size;
|
||||
extern const DSPOPCTemplate opcodes_ext[];
|
||||
extern const int opcodes_ext_size;
|
||||
extern u8 opSize[OPTABLE_SIZE];
|
||||
extern const DSPOPCTemplate cw;
|
||||
|
||||
extern dspInstFunc opTable[];
|
||||
extern dspInstFunc prologueTable[OPTABLE_SIZE];
|
||||
extern dspInstFunc epilogueTable[OPTABLE_SIZE];
|
||||
|
||||
// Predefined labels
|
||||
struct pdlabel_t
|
||||
{
|
||||
u16 addr;
|
||||
const char* name;
|
||||
const char* description;
|
||||
};
|
||||
|
||||
extern const pdlabel_t regnames[];
|
||||
extern const pdlabel_t pdlabels[];
|
||||
extern const u32 pdlabels_size;
|
||||
|
||||
const char *pdname(u16 val);
|
||||
const char *pdregname(int val);
|
||||
const char *pdregnamelong(int val);
|
||||
|
||||
void InitInstructionTable();
|
||||
|
||||
inline void ExecuteInstruction(const UDSPInstruction& inst)
|
||||
{
|
||||
// TODO: Move the prologuetable calls into the relevant instructions themselves.
|
||||
// Better not do things like this until things work correctly though.
|
||||
if (prologueTable[inst.hex])
|
||||
prologueTable[inst.hex](inst);
|
||||
opTable[inst.hex](inst);
|
||||
if (epilogueTable[inst.hex])
|
||||
epilogueTable[inst.hex](inst);
|
||||
}
|
||||
|
||||
// This one's pretty slow, try to use it only at init or seldomly.
|
||||
// returns NULL if no matching instruction.
|
||||
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
|
||||
|
||||
#endif // _DSPTABLES_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,249 +1,249 @@
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPMemoryMap.h"
|
||||
#include "DSPStacks.h"
|
||||
|
||||
#include "DSPIntCCUtil.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
// Generic call implementation
|
||||
// CALLcc addressA
|
||||
// 0000 0010 1011 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to $st0. Set program counter to address
|
||||
// represented by value that follows this "call" instruction.
|
||||
void call(const UDSPInstruction& opc)
|
||||
{
|
||||
// must be outside the if.
|
||||
u16 dest = dsp_fetch_code();
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
g_dsp.pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic callr implementation
|
||||
// CALLRcc $R
|
||||
// 0001 0111 rrr1 cccc
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to call stack $st0. Set program counter to
|
||||
// register $R.
|
||||
void callr(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
u8 reg = (opc.hex >> 5) & 0x7;
|
||||
u16 addr = dsp_op_read_reg(reg);
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
g_dsp.pc = addr;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic if implementation
|
||||
// IFcc
|
||||
// 0000 0010 0111 cccc
|
||||
// Execute following opcode if the condition has been met.
|
||||
void ifcc(const UDSPInstruction& opc)
|
||||
{
|
||||
if (!CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
// skip the next opcode - we have to lookup its size.
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
// Generic jmp implementation
|
||||
// Jcc addressA
|
||||
// 0000 0010 1001 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Jump to addressA if condition cc has been met. Set program counter to
|
||||
// address represented by value that follows this "jmp" instruction.
|
||||
void jcc(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 dest = dsp_fetch_code();
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
g_dsp.pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic jmpr implementation
|
||||
// JMPcc $R
|
||||
// 0001 0111 rrr0 cccc
|
||||
// Jump to address; set program counter to a value from register $R.
|
||||
void jmprcc(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
u8 reg = (opc.hex >> 5) & 0x7;
|
||||
g_dsp.pc = dsp_op_read_reg(reg);
|
||||
}
|
||||
}
|
||||
|
||||
// Generic ret implementation
|
||||
// RETcc
|
||||
// 0000 0010 1101 cccc
|
||||
// Return from subroutine if condition cc has been met. Pops stored PC
|
||||
// from call stack $st0 and sets $pc to this location.
|
||||
void ret(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||
}
|
||||
}
|
||||
|
||||
// RTI
|
||||
// 0000 0010 1111 1111
|
||||
// Return from exception. Pops stored status register $sr from data stack
|
||||
// $st1 and program counter PC from call stack $st0 and sets $pc to this
|
||||
// location.
|
||||
void rti(const UDSPInstruction& opc)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
|
||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||
|
||||
g_dsp.exception_in_progress_hack = false;
|
||||
}
|
||||
|
||||
// HALT
|
||||
// 0000 0000 0020 0001
|
||||
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
|
||||
void halt(const UDSPInstruction& opc)
|
||||
{
|
||||
g_dsp.cr |= 0x4;
|
||||
g_dsp.pc--;
|
||||
}
|
||||
|
||||
|
||||
// LOOP handling: Loop stack is used to control execution of repeated blocks of
|
||||
// instructions. Whenever there is value on stack $st2 and current PC is equal
|
||||
// value at $st2, then value at stack $st3 is decremented. If value is not zero
|
||||
// then PC is modified with calue from call stack $st0. Otherwise values from
|
||||
// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
|
||||
// continues at next opcode.
|
||||
|
||||
|
||||
// LOOP $R
|
||||
// 0000 0000 010r rrrr
|
||||
// Repeatedly execute following opcode until counter specified by value
|
||||
// from register $R reaches zero. Each execution decrement counter. Register
|
||||
// $R remains unchanged. If register $R is set to zero at the beginning of loop
|
||||
// then looped instruction will not get executed.
|
||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||
// The looping hardware takes care of the rest.
|
||||
void loop(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x1f;
|
||||
u16 cnt = g_dsp.r[reg];
|
||||
u16 loop_pc = g_dsp.pc;
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
// LOOPI #I
|
||||
// 0001 0000 iiii iiii
|
||||
// Repeatedly execute following opcode until counter specified by
|
||||
// immediate value I reaches zero. Each execution decrement counter. If
|
||||
// immediate value I is set to zero at the beginning of loop then looped
|
||||
// instruction will not get executed.
|
||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||
// The looping hardware takes care of the rest.
|
||||
void loopi(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 cnt = opc.hex & 0xff;
|
||||
u16 loop_pc = g_dsp.pc;
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// BLOOP $R, addrA
|
||||
// 0000 0000 011r rrrr
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Repeatedly execute block of code starting at following opcode until
|
||||
// counter specified by value from register $R reaches zero. Block ends at
|
||||
// specified address addrA inclusive, ie. opcode at addrA is the last opcode
|
||||
// included in loop. Counter is pushed on loop stack $st3, end of block address
|
||||
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
|
||||
// Up to 4 nested loops is allowed.
|
||||
void bloop(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x1f;
|
||||
u16 cnt = g_dsp.r[reg];
|
||||
u16 loop_pc = dsp_fetch_code();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.pc = loop_pc;
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
// BLOOPI #I, addrA
|
||||
// 0001 0001 iiii iiii
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Repeatedly execute block of code starting at following opcode until
|
||||
// counter specified by immediate value I reaches zero. Block ends at specified
|
||||
// address addrA inclusive, ie. opcode at addrA is the last opcode included in
|
||||
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
|
||||
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
|
||||
// nested loops is allowed.
|
||||
void bloopi(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 cnt = opc.hex & 0xff;
|
||||
u16 loop_pc = dsp_fetch_code();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.pc = loop_pc;
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPMemoryMap.h"
|
||||
#include "DSPStacks.h"
|
||||
|
||||
#include "DSPIntCCUtil.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
// Generic call implementation
|
||||
// CALLcc addressA
|
||||
// 0000 0010 1011 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to $st0. Set program counter to address
|
||||
// represented by value that follows this "call" instruction.
|
||||
void call(const UDSPInstruction& opc)
|
||||
{
|
||||
// must be outside the if.
|
||||
u16 dest = dsp_fetch_code();
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
g_dsp.pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic callr implementation
|
||||
// CALLRcc $R
|
||||
// 0001 0111 rrr1 cccc
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to call stack $st0. Set program counter to
|
||||
// register $R.
|
||||
void callr(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
u8 reg = (opc.hex >> 5) & 0x7;
|
||||
u16 addr = dsp_op_read_reg(reg);
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
g_dsp.pc = addr;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic if implementation
|
||||
// IFcc
|
||||
// 0000 0010 0111 cccc
|
||||
// Execute following opcode if the condition has been met.
|
||||
void ifcc(const UDSPInstruction& opc)
|
||||
{
|
||||
if (!CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
// skip the next opcode - we have to lookup its size.
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
// Generic jmp implementation
|
||||
// Jcc addressA
|
||||
// 0000 0010 1001 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Jump to addressA if condition cc has been met. Set program counter to
|
||||
// address represented by value that follows this "jmp" instruction.
|
||||
void jcc(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 dest = dsp_fetch_code();
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
g_dsp.pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic jmpr implementation
|
||||
// JMPcc $R
|
||||
// 0001 0111 rrr0 cccc
|
||||
// Jump to address; set program counter to a value from register $R.
|
||||
void jmprcc(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
u8 reg = (opc.hex >> 5) & 0x7;
|
||||
g_dsp.pc = dsp_op_read_reg(reg);
|
||||
}
|
||||
}
|
||||
|
||||
// Generic ret implementation
|
||||
// RETcc
|
||||
// 0000 0010 1101 cccc
|
||||
// Return from subroutine if condition cc has been met. Pops stored PC
|
||||
// from call stack $st0 and sets $pc to this location.
|
||||
void ret(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||
}
|
||||
}
|
||||
|
||||
// RTI
|
||||
// 0000 0010 1111 1111
|
||||
// Return from exception. Pops stored status register $sr from data stack
|
||||
// $st1 and program counter PC from call stack $st0 and sets $pc to this
|
||||
// location.
|
||||
void rti(const UDSPInstruction& opc)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
|
||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||
|
||||
g_dsp.exception_in_progress_hack = false;
|
||||
}
|
||||
|
||||
// HALT
|
||||
// 0000 0000 0020 0001
|
||||
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
|
||||
void halt(const UDSPInstruction& opc)
|
||||
{
|
||||
g_dsp.cr |= 0x4;
|
||||
g_dsp.pc--;
|
||||
}
|
||||
|
||||
|
||||
// LOOP handling: Loop stack is used to control execution of repeated blocks of
|
||||
// instructions. Whenever there is value on stack $st2 and current PC is equal
|
||||
// value at $st2, then value at stack $st3 is decremented. If value is not zero
|
||||
// then PC is modified with calue from call stack $st0. Otherwise values from
|
||||
// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
|
||||
// continues at next opcode.
|
||||
|
||||
|
||||
// LOOP $R
|
||||
// 0000 0000 010r rrrr
|
||||
// Repeatedly execute following opcode until counter specified by value
|
||||
// from register $R reaches zero. Each execution decrement counter. Register
|
||||
// $R remains unchanged. If register $R is set to zero at the beginning of loop
|
||||
// then looped instruction will not get executed.
|
||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||
// The looping hardware takes care of the rest.
|
||||
void loop(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x1f;
|
||||
u16 cnt = g_dsp.r[reg];
|
||||
u16 loop_pc = g_dsp.pc;
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
// LOOPI #I
|
||||
// 0001 0000 iiii iiii
|
||||
// Repeatedly execute following opcode until counter specified by
|
||||
// immediate value I reaches zero. Each execution decrement counter. If
|
||||
// immediate value I is set to zero at the beginning of loop then looped
|
||||
// instruction will not get executed.
|
||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||
// The looping hardware takes care of the rest.
|
||||
void loopi(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 cnt = opc.hex & 0xff;
|
||||
u16 loop_pc = g_dsp.pc;
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// BLOOP $R, addrA
|
||||
// 0000 0000 011r rrrr
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Repeatedly execute block of code starting at following opcode until
|
||||
// counter specified by value from register $R reaches zero. Block ends at
|
||||
// specified address addrA inclusive, ie. opcode at addrA is the last opcode
|
||||
// included in loop. Counter is pushed on loop stack $st3, end of block address
|
||||
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
|
||||
// Up to 4 nested loops is allowed.
|
||||
void bloop(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x1f;
|
||||
u16 cnt = g_dsp.r[reg];
|
||||
u16 loop_pc = dsp_fetch_code();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.pc = loop_pc;
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
// BLOOPI #I, addrA
|
||||
// 0001 0001 iiii iiii
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Repeatedly execute block of code starting at following opcode until
|
||||
// counter specified by immediate value I reaches zero. Block ends at specified
|
||||
// address addrA inclusive, ie. opcode at addrA is the last opcode included in
|
||||
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
|
||||
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
|
||||
// nested loops is allowed.
|
||||
void bloopi(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 cnt = opc.hex & 0xff;
|
||||
u16 loop_pc = dsp_fetch_code();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.pc = loop_pc;
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1,266 +1,266 @@
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
#include "DSPMemoryMap.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
// SRS @M, $(0x18+S)
|
||||
// 0010 1sss mmmm mmmm
|
||||
// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
|
||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||
// lower 8 bits are from the 8-bit immediate.
|
||||
// Note: pc+=2 in duddie's doc seems wrong
|
||||
void srs(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||
dsp_dmem_write(addr, g_dsp.r[reg]);
|
||||
}
|
||||
|
||||
// LRS $(0x18+D), @M
|
||||
// 0010 0ddd mmmm mmmm
|
||||
// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
|
||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||
// lower 8 bits are from the 8-bit immediate.
|
||||
void lrs(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||
g_dsp.r[reg] = dsp_dmem_read(addr);
|
||||
}
|
||||
|
||||
// LR $D, @M
|
||||
// 0000 0000 110d dddd
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Move value from data memory pointed by address M to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 addr = dsp_fetch_code();
|
||||
u16 val = dsp_dmem_read(addr);
|
||||
dsp_op_write_reg(reg, val);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// SR @M, $S
|
||||
// 0000 0000 111s ssss
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Store value from register $S to a memory pointed by address M.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void sr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 addr = dsp_fetch_code();
|
||||
u16 val = dsp_op_read_reg(reg);
|
||||
dsp_dmem_write(addr, val);
|
||||
}
|
||||
|
||||
// SI @M, #I
|
||||
// 0001 0110 mmmm mmmm
|
||||
// iiii iiii iiii iiii
|
||||
// Store 16-bit immediate value I to a memory location pointed by address
|
||||
// M (M is 8-bit value sign extended).
|
||||
void si(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 addr = (s8)opc.hex;
|
||||
u16 imm = dsp_fetch_code();
|
||||
dsp_dmem_write(addr, imm);
|
||||
}
|
||||
|
||||
// LRR $D, @$S
|
||||
// 0001 1000 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
}
|
||||
|
||||
// LRRD $D, @$S
|
||||
// 0001 1000 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S toregister $D.
|
||||
// Decrement register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
dsp_decrement_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRI $D, @$S
|
||||
// 0001 1001 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Increment register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
dsp_increment_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRN $D, @$S
|
||||
// 0001 1001 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Add indexing register $(0x4+S) to register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
// g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
|
||||
dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
}
|
||||
|
||||
// SRR @$D, $S
|
||||
// 0001 1010 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
}
|
||||
|
||||
// SRRD @$D, $S
|
||||
// 0001 1010 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Decrement register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
dsp_decrement_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRI @$D, $S
|
||||
// 0001 1011 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Increment register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
dsp_increment_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRN @$D, $S
|
||||
// 0001 1011 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
// g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
|
||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
|
||||
}
|
||||
|
||||
// ILRR $acD.m, @$arS
|
||||
// 0000 001d 0001 00ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m.
|
||||
void ilrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
}
|
||||
|
||||
// ILRRD $acD.m, @$arS
|
||||
// 0000 001d 0001 01ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
|
||||
void ilrrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
dsp_decrement_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRI $acD.m, @$S
|
||||
// 0000 001d 0001 10ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
|
||||
void ilrri(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
dsp_increment_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRN $acD.m, @$arS
|
||||
// 0000 001d 0001 11ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Add corresponding indexing
|
||||
// register $ixS to addressing register $arS.
|
||||
void ilrrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
// g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
|
||||
dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
#include "DSPMemoryMap.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
// SRS @M, $(0x18+S)
|
||||
// 0010 1sss mmmm mmmm
|
||||
// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
|
||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||
// lower 8 bits are from the 8-bit immediate.
|
||||
// Note: pc+=2 in duddie's doc seems wrong
|
||||
void srs(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||
dsp_dmem_write(addr, g_dsp.r[reg]);
|
||||
}
|
||||
|
||||
// LRS $(0x18+D), @M
|
||||
// 0010 0ddd mmmm mmmm
|
||||
// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
|
||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||
// lower 8 bits are from the 8-bit immediate.
|
||||
void lrs(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||
g_dsp.r[reg] = dsp_dmem_read(addr);
|
||||
}
|
||||
|
||||
// LR $D, @M
|
||||
// 0000 0000 110d dddd
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Move value from data memory pointed by address M to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 addr = dsp_fetch_code();
|
||||
u16 val = dsp_dmem_read(addr);
|
||||
dsp_op_write_reg(reg, val);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// SR @M, $S
|
||||
// 0000 0000 111s ssss
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Store value from register $S to a memory pointed by address M.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void sr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 addr = dsp_fetch_code();
|
||||
u16 val = dsp_op_read_reg(reg);
|
||||
dsp_dmem_write(addr, val);
|
||||
}
|
||||
|
||||
// SI @M, #I
|
||||
// 0001 0110 mmmm mmmm
|
||||
// iiii iiii iiii iiii
|
||||
// Store 16-bit immediate value I to a memory location pointed by address
|
||||
// M (M is 8-bit value sign extended).
|
||||
void si(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 addr = (s8)opc.hex;
|
||||
u16 imm = dsp_fetch_code();
|
||||
dsp_dmem_write(addr, imm);
|
||||
}
|
||||
|
||||
// LRR $D, @$S
|
||||
// 0001 1000 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
}
|
||||
|
||||
// LRRD $D, @$S
|
||||
// 0001 1000 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S toregister $D.
|
||||
// Decrement register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
dsp_decrement_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRI $D, @$S
|
||||
// 0001 1001 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Increment register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
dsp_increment_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRN $D, @$S
|
||||
// 0001 1001 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Add indexing register $(0x4+S) to register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
// g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
|
||||
dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
}
|
||||
|
||||
// SRR @$D, $S
|
||||
// 0001 1010 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
}
|
||||
|
||||
// SRRD @$D, $S
|
||||
// 0001 1010 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Decrement register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
dsp_decrement_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRI @$D, $S
|
||||
// 0001 1011 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Increment register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
dsp_increment_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRN @$D, $S
|
||||
// 0001 1011 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
// g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
|
||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
|
||||
}
|
||||
|
||||
// ILRR $acD.m, @$arS
|
||||
// 0000 001d 0001 00ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m.
|
||||
void ilrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
}
|
||||
|
||||
// ILRRD $acD.m, @$arS
|
||||
// 0000 001d 0001 01ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
|
||||
void ilrrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
dsp_decrement_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRI $acD.m, @$S
|
||||
// 0000 001d 0001 10ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
|
||||
void ilrri(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
dsp_increment_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRN $acD.m, @$arS
|
||||
// 0000 001d 0001 11ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Add corresponding indexing
|
||||
// register $ixS to addressing register $arS.
|
||||
void ilrrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
// g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
|
||||
dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1,202 +1,202 @@
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
#include "DSPCore.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void unknown(const UDSPInstruction& opc)
|
||||
{
|
||||
//_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||
ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
|
||||
}
|
||||
|
||||
// MRR $D, $S
|
||||
// 0001 11dd ddds ssss
|
||||
// Move value from register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void mrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
u8 dreg = (opc.hex >> 5) & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
}
|
||||
|
||||
// LRI $D, #I
|
||||
// 0000 0000 100d dddd
|
||||
// iiii iiii iiii iiii
|
||||
// Load immediate value I to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
|
||||
// DSPSpy discovery: This, and possibly other instructions that load a register,
|
||||
// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
|
||||
// to the whole accumulator! This does not happen in S16 mode.
|
||||
void lri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 imm = dsp_fetch_code();
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// LRIS $(0x18+D), #I
|
||||
// 0000 1ddd iiii iiii
|
||||
// Load immediate value I (8-bit sign extended) to accumulator register.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lris(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
|
||||
u16 imm = (s8)opc.hex;
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
|
||||
// TSTAXL $acR
|
||||
// 1000 r001 xxxx xxxx
|
||||
// r specifies one of the main accumulators.
|
||||
// Definitely not a test instruction - it changes the accums.
|
||||
// Not affected by m0/m2. Not affected by s16/s40.
|
||||
void tstaxl(const UDSPInstruction& opc)
|
||||
{
|
||||
// This is probably all wrong.
|
||||
//u8 reg = (opc.hex >> 8) & 0x1;
|
||||
//s16 val = dsp_get_ax_l(reg);
|
||||
//Update_SR_Register16(val);
|
||||
}
|
||||
|
||||
// ADDARN $arD, $ixS
|
||||
// 0000 0000 0001 ssdd
|
||||
// Adds indexing register $ixS to an addressing register $arD.
|
||||
void addarn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = opc.hex & 0x3;
|
||||
u8 sreg = (opc.hex >> 2) & 0x3;
|
||||
|
||||
// g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
|
||||
|
||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
|
||||
// It is critical for the Zelda ucode that this one wraps correctly.
|
||||
}
|
||||
|
||||
// NX
|
||||
// 1000 -000 xxxx xxxx
|
||||
// No operation, but can be extended with extended opcode.
|
||||
void nx(const UDSPInstruction& opc)
|
||||
{
|
||||
// This opcode is supposed to do nothing - it's used if you want to use
|
||||
// an opcode extension but not do anything. At least according to duddie.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// DAR $arD ?
|
||||
// 0000 0000 0000 01dd
|
||||
// Decrement address register $arD.
|
||||
void dar(const UDSPInstruction& opc)
|
||||
{
|
||||
dsp_decrement_addr_reg(opc.hex & 0x3);
|
||||
}
|
||||
|
||||
// IAR $arD ?
|
||||
// 0000 0000 0000 10dd
|
||||
// Increment address register $arD.
|
||||
void iar(const UDSPInstruction& opc)
|
||||
{
|
||||
dsp_increment_addr_reg(opc.hex & 0x3);
|
||||
}
|
||||
|
||||
// SBCLR #I
|
||||
// 0001 0011 0000 0iii
|
||||
// bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void sbclr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 bit = (opc.hex & 0xff) + 6;
|
||||
g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
|
||||
}
|
||||
|
||||
// SBSET #I
|
||||
// 0001 0010 0000 0iii
|
||||
// Set bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void sbset(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 bit = (opc.hex & 0xff) + 6;
|
||||
g_dsp.r[DSP_REG_SR] |= (1 << bit);
|
||||
}
|
||||
|
||||
|
||||
// FIXME inside
|
||||
// This is a bunch of flag setters, flipping bits in SR. So far so good,
|
||||
// but it's harder to know exactly what effect they have.
|
||||
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
|
||||
//
|
||||
// SET16 changes something very important: see the LRI instruction above.
|
||||
// Hermes' demo sets the following defaults:
|
||||
// SET40
|
||||
// CLR15
|
||||
// M0
|
||||
void srbith(const UDSPInstruction& opc)
|
||||
{
|
||||
switch ((opc.hex >> 8) & 0xf)
|
||||
{
|
||||
// M0 seems to be the default. M2 is used in functions in Zelda
|
||||
// and then reset with M0 at the end. Like the other bits here, it's
|
||||
// done around loops with lots of multiplications.
|
||||
// I've confirmed with DSPSpy that they flip this bit.
|
||||
case 0xa: // M2
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
|
||||
break;
|
||||
case 0xb: // M0
|
||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
|
||||
break;
|
||||
|
||||
// If set, treat multiplicands as unsigned.
|
||||
// If clear, treat them as signed.
|
||||
case 0xc: // CLR15
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
|
||||
break;
|
||||
case 0xd: // SET15
|
||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
|
||||
break;
|
||||
|
||||
// Automatic 40-bit sign extension when loading ACx.M.
|
||||
// 40 seems to be the default.
|
||||
// Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
|
||||
case 0xe: // SET16 (really, clear SR's 0x4000)
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
|
||||
break;
|
||||
|
||||
case 0xf: // SET40 (really, set SR's 0x4000)
|
||||
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
#include "DSPCore.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void unknown(const UDSPInstruction& opc)
|
||||
{
|
||||
//_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||
ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
|
||||
}
|
||||
|
||||
// MRR $D, $S
|
||||
// 0001 11dd ddds ssss
|
||||
// Move value from register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void mrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
u8 dreg = (opc.hex >> 5) & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
}
|
||||
|
||||
// LRI $D, #I
|
||||
// 0000 0000 100d dddd
|
||||
// iiii iiii iiii iiii
|
||||
// Load immediate value I to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
|
||||
// DSPSpy discovery: This, and possibly other instructions that load a register,
|
||||
// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
|
||||
// to the whole accumulator! This does not happen in S16 mode.
|
||||
void lri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 imm = dsp_fetch_code();
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// LRIS $(0x18+D), #I
|
||||
// 0000 1ddd iiii iiii
|
||||
// Load immediate value I (8-bit sign extended) to accumulator register.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lris(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
|
||||
u16 imm = (s8)opc.hex;
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
|
||||
// TSTAXL $acR
|
||||
// 1000 r001 xxxx xxxx
|
||||
// r specifies one of the main accumulators.
|
||||
// Definitely not a test instruction - it changes the accums.
|
||||
// Not affected by m0/m2. Not affected by s16/s40.
|
||||
void tstaxl(const UDSPInstruction& opc)
|
||||
{
|
||||
// This is probably all wrong.
|
||||
//u8 reg = (opc.hex >> 8) & 0x1;
|
||||
//s16 val = dsp_get_ax_l(reg);
|
||||
//Update_SR_Register16(val);
|
||||
}
|
||||
|
||||
// ADDARN $arD, $ixS
|
||||
// 0000 0000 0001 ssdd
|
||||
// Adds indexing register $ixS to an addressing register $arD.
|
||||
void addarn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = opc.hex & 0x3;
|
||||
u8 sreg = (opc.hex >> 2) & 0x3;
|
||||
|
||||
// g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
|
||||
|
||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
|
||||
// It is critical for the Zelda ucode that this one wraps correctly.
|
||||
}
|
||||
|
||||
// NX
|
||||
// 1000 -000 xxxx xxxx
|
||||
// No operation, but can be extended with extended opcode.
|
||||
void nx(const UDSPInstruction& opc)
|
||||
{
|
||||
// This opcode is supposed to do nothing - it's used if you want to use
|
||||
// an opcode extension but not do anything. At least according to duddie.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// DAR $arD ?
|
||||
// 0000 0000 0000 01dd
|
||||
// Decrement address register $arD.
|
||||
void dar(const UDSPInstruction& opc)
|
||||
{
|
||||
dsp_decrement_addr_reg(opc.hex & 0x3);
|
||||
}
|
||||
|
||||
// IAR $arD ?
|
||||
// 0000 0000 0000 10dd
|
||||
// Increment address register $arD.
|
||||
void iar(const UDSPInstruction& opc)
|
||||
{
|
||||
dsp_increment_addr_reg(opc.hex & 0x3);
|
||||
}
|
||||
|
||||
// SBCLR #I
|
||||
// 0001 0011 0000 0iii
|
||||
// bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void sbclr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 bit = (opc.hex & 0xff) + 6;
|
||||
g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
|
||||
}
|
||||
|
||||
// SBSET #I
|
||||
// 0001 0010 0000 0iii
|
||||
// Set bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void sbset(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 bit = (opc.hex & 0xff) + 6;
|
||||
g_dsp.r[DSP_REG_SR] |= (1 << bit);
|
||||
}
|
||||
|
||||
|
||||
// FIXME inside
|
||||
// This is a bunch of flag setters, flipping bits in SR. So far so good,
|
||||
// but it's harder to know exactly what effect they have.
|
||||
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
|
||||
//
|
||||
// SET16 changes something very important: see the LRI instruction above.
|
||||
// Hermes' demo sets the following defaults:
|
||||
// SET40
|
||||
// CLR15
|
||||
// M0
|
||||
void srbith(const UDSPInstruction& opc)
|
||||
{
|
||||
switch ((opc.hex >> 8) & 0xf)
|
||||
{
|
||||
// M0 seems to be the default. M2 is used in functions in Zelda
|
||||
// and then reset with M0 at the end. Like the other bits here, it's
|
||||
// done around loops with lots of multiplications.
|
||||
// I've confirmed with DSPSpy that they flip this bit.
|
||||
case 0xa: // M2
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
|
||||
break;
|
||||
case 0xb: // M0
|
||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
|
||||
break;
|
||||
|
||||
// If set, treat multiplicands as unsigned.
|
||||
// If clear, treat them as signed.
|
||||
case 0xc: // CLR15
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
|
||||
break;
|
||||
case 0xd: // SET15
|
||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
|
||||
break;
|
||||
|
||||
// Automatic 40-bit sign extension when loading ACx.M.
|
||||
// 40 seems to be the default.
|
||||
// Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
|
||||
case 0xe: // SET16 (really, clear SR's 0x4000)
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
|
||||
break;
|
||||
|
||||
case 0xf: // SET40 (really, set SR's 0x4000)
|
||||
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,85 +1,85 @@
|
||||
// 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 "LabelMap.h"
|
||||
#include "DSPTables.h"
|
||||
|
||||
LabelMap::LabelMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LabelMap::RegisterDefaults()
|
||||
{
|
||||
for (int i = 0; i < 0x24; i++)
|
||||
{
|
||||
if (regnames[i].name)
|
||||
RegisterLabel(regnames[i].name, regnames[i].addr);
|
||||
}
|
||||
for (int i = 0; i < (int)pdlabels_size; i++)
|
||||
{
|
||||
if (pdlabels[i].name)
|
||||
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
|
||||
{
|
||||
u16 old_value;
|
||||
if (GetLabelValue(label, &old_value) && old_value != lval)
|
||||
{
|
||||
printf("WARNING: Redefined label %s to %04x - old value %04x\n",
|
||||
label.c_str(), lval, old_value);
|
||||
DeleteLabel(label);
|
||||
}
|
||||
labels.push_back(label_t(label, lval, type));
|
||||
}
|
||||
|
||||
void LabelMap::DeleteLabel(const std::string &label)
|
||||
{
|
||||
for (std::vector<label_t>::iterator iter = labels.begin();
|
||||
iter != labels.end(); ++iter)
|
||||
{
|
||||
if (!label.compare(iter->name))
|
||||
{
|
||||
labels.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
|
||||
{
|
||||
for (u32 i = 0; i < labels.size(); i++)
|
||||
{
|
||||
if (!label.compare(labels[i].name))
|
||||
{
|
||||
if (type & labels[i].type) {
|
||||
*value = labels[i].addr;
|
||||
return true;
|
||||
} else {
|
||||
printf("WARNING: Wrong label type requested. %s\n", label.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LabelMap::Clear()
|
||||
{
|
||||
labels.clear();
|
||||
}
|
||||
// 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 "LabelMap.h"
|
||||
#include "DSPTables.h"
|
||||
|
||||
LabelMap::LabelMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LabelMap::RegisterDefaults()
|
||||
{
|
||||
for (int i = 0; i < 0x24; i++)
|
||||
{
|
||||
if (regnames[i].name)
|
||||
RegisterLabel(regnames[i].name, regnames[i].addr);
|
||||
}
|
||||
for (int i = 0; i < (int)pdlabels_size; i++)
|
||||
{
|
||||
if (pdlabels[i].name)
|
||||
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
|
||||
{
|
||||
u16 old_value;
|
||||
if (GetLabelValue(label, &old_value) && old_value != lval)
|
||||
{
|
||||
printf("WARNING: Redefined label %s to %04x - old value %04x\n",
|
||||
label.c_str(), lval, old_value);
|
||||
DeleteLabel(label);
|
||||
}
|
||||
labels.push_back(label_t(label, lval, type));
|
||||
}
|
||||
|
||||
void LabelMap::DeleteLabel(const std::string &label)
|
||||
{
|
||||
for (std::vector<label_t>::iterator iter = labels.begin();
|
||||
iter != labels.end(); ++iter)
|
||||
{
|
||||
if (!label.compare(iter->name))
|
||||
{
|
||||
labels.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
|
||||
{
|
||||
for (u32 i = 0; i < labels.size(); i++)
|
||||
{
|
||||
if (!label.compare(labels[i].name))
|
||||
{
|
||||
if (type & labels[i].type) {
|
||||
*value = labels[i].addr;
|
||||
return true;
|
||||
} else {
|
||||
printf("WARNING: Wrong label type requested. %s\n", label.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LabelMap::Clear()
|
||||
{
|
||||
labels.clear();
|
||||
}
|
||||
|
@ -1,55 +1,55 @@
|
||||
// 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/
|
||||
|
||||
#ifndef _LABELMAP_H
|
||||
#define _LABELMAP_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
enum LabelType
|
||||
{
|
||||
LABEL_IADDR = 1, // Jump addresses, etc
|
||||
LABEL_DADDR = 2, // Data addresses, etc
|
||||
LABEL_VALUE = 4,
|
||||
LABEL_ANY = 0xFF,
|
||||
};
|
||||
|
||||
class LabelMap
|
||||
{
|
||||
struct label_t
|
||||
{
|
||||
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
|
||||
std::string name;
|
||||
s32 addr;
|
||||
LabelType type;
|
||||
};
|
||||
std::vector<label_t> labels;
|
||||
|
||||
public:
|
||||
LabelMap();
|
||||
~LabelMap() { }
|
||||
void RegisterDefaults();
|
||||
void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
|
||||
void DeleteLabel(const std::string &label);
|
||||
bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
|
||||
void Clear();
|
||||
};
|
||||
|
||||
#endif // _LABELMAP_H
|
||||
// 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/
|
||||
|
||||
#ifndef _LABELMAP_H
|
||||
#define _LABELMAP_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
enum LabelType
|
||||
{
|
||||
LABEL_IADDR = 1, // Jump addresses, etc
|
||||
LABEL_DADDR = 2, // Data addresses, etc
|
||||
LABEL_VALUE = 4,
|
||||
LABEL_ANY = 0xFF,
|
||||
};
|
||||
|
||||
class LabelMap
|
||||
{
|
||||
struct label_t
|
||||
{
|
||||
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
|
||||
std::string name;
|
||||
s32 addr;
|
||||
LabelType type;
|
||||
};
|
||||
std::vector<label_t> labels;
|
||||
|
||||
public:
|
||||
LabelMap();
|
||||
~LabelMap() { }
|
||||
void RegisterDefaults();
|
||||
void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
|
||||
void DeleteLabel(const std::string &label);
|
||||
bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
|
||||
void Clear();
|
||||
};
|
||||
|
||||
#endif // _LABELMAP_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,139 +1,139 @@
|
||||
/*====================================================================
|
||||
|
||||
project: GameCube DSP Tool (gcdsp)
|
||||
created: 2005.03.04
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#ifndef _DSP_ASSEMBLE_H
|
||||
#define _DSP_ASSEMBLE_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "disassemble.h"
|
||||
#include "DSPTables.h"
|
||||
#include "LabelMap.h"
|
||||
|
||||
enum err_t
|
||||
{
|
||||
ERR_OK = 0,
|
||||
ERR_UNKNOWN,
|
||||
ERR_UNKNOWN_OPCODE,
|
||||
ERR_NOT_ENOUGH_PARAMETERS,
|
||||
ERR_TOO_MANY_PARAMETERS,
|
||||
ERR_WRONG_PARAMETER,
|
||||
ERR_EXPECTED_PARAM_STR,
|
||||
ERR_EXPECTED_PARAM_VAL,
|
||||
ERR_EXPECTED_PARAM_REG,
|
||||
ERR_EXPECTED_PARAM_MEM,
|
||||
ERR_EXPECTED_PARAM_IMM,
|
||||
ERR_INCORRECT_BIN,
|
||||
ERR_INCORRECT_HEX,
|
||||
ERR_INCORRECT_DEC,
|
||||
ERR_LABEL_EXISTS,
|
||||
ERR_UNKNOWN_LABEL,
|
||||
ERR_NO_MATCHING_BRACKETS,
|
||||
ERR_EXT_CANT_EXTEND_OPCODE,
|
||||
ERR_EXT_PAR_NOT_EXT,
|
||||
ERR_WRONG_PARAMETER_ACC,
|
||||
ERR_WRONG_PARAMETER_MID_ACC,
|
||||
ERR_INVALID_REGISTER,
|
||||
ERR_OUT_RANGE_NUMBER
|
||||
};
|
||||
|
||||
|
||||
// Unless you want labels to carry over between files, you probably
|
||||
// want to create a new DSPAssembler for every file you assemble.
|
||||
class DSPAssembler
|
||||
{
|
||||
public:
|
||||
DSPAssembler(const AssemblerSettings &settings);
|
||||
~DSPAssembler();
|
||||
|
||||
// line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
|
||||
// one for each word of code, indicating the source assembler code line number it came from.
|
||||
|
||||
// If returns false, call GetErrorString to get some text to present to the user.
|
||||
bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
|
||||
|
||||
std::string GetErrorString() const { return last_error_str; }
|
||||
err_t GetError() const { return last_error; }
|
||||
|
||||
private:
|
||||
struct param_t
|
||||
{
|
||||
u32 val;
|
||||
partype_t type;
|
||||
char *str;
|
||||
};
|
||||
|
||||
enum segment_t
|
||||
{
|
||||
SEGMENT_CODE = 0,
|
||||
SEGMENT_DATA,
|
||||
SEGMENT_OVERLAY,
|
||||
SEGMENT_MAX
|
||||
};
|
||||
|
||||
// Utility functions
|
||||
s32 ParseValue(const char *str);
|
||||
u32 ParseExpression(const char *ptr);
|
||||
|
||||
u32 GetParams(char *parstr, param_t *par);
|
||||
|
||||
void InitPass(int pass);
|
||||
bool AssembleFile(const char *fname, int pass);
|
||||
|
||||
void ShowError(err_t err_code, const char *extra_info = NULL);
|
||||
// void ShowWarning(err_t err_code, const char *extra_info = NULL);
|
||||
|
||||
char *FindBrackets(char *src, char *dst);
|
||||
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
|
||||
bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
|
||||
void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
|
||||
|
||||
char *gdg_buffer;
|
||||
|
||||
std::string include_dir;
|
||||
std::string cur_line;
|
||||
|
||||
u32 m_cur_addr;
|
||||
int m_totalSize;
|
||||
u8 m_cur_pass;
|
||||
|
||||
LabelMap labels;
|
||||
|
||||
u32 code_line;
|
||||
bool failed;
|
||||
std::string last_error_str;
|
||||
err_t last_error;
|
||||
|
||||
typedef std::map<std::string, std::string> AliasMap;
|
||||
AliasMap aliases;
|
||||
|
||||
segment_t cur_segment;
|
||||
u32 segment_addr[SEGMENT_MAX];
|
||||
int m_current_param;
|
||||
const AssemblerSettings settings_;
|
||||
};
|
||||
|
||||
#endif // _DSP_ASSEMBLE_H
|
||||
/*====================================================================
|
||||
|
||||
project: GameCube DSP Tool (gcdsp)
|
||||
created: 2005.03.04
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie
|
||||
|
||||
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; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#ifndef _DSP_ASSEMBLE_H
|
||||
#define _DSP_ASSEMBLE_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "disassemble.h"
|
||||
#include "DSPTables.h"
|
||||
#include "LabelMap.h"
|
||||
|
||||
enum err_t
|
||||
{
|
||||
ERR_OK = 0,
|
||||
ERR_UNKNOWN,
|
||||
ERR_UNKNOWN_OPCODE,
|
||||
ERR_NOT_ENOUGH_PARAMETERS,
|
||||
ERR_TOO_MANY_PARAMETERS,
|
||||
ERR_WRONG_PARAMETER,
|
||||
ERR_EXPECTED_PARAM_STR,
|
||||
ERR_EXPECTED_PARAM_VAL,
|
||||
ERR_EXPECTED_PARAM_REG,
|
||||
ERR_EXPECTED_PARAM_MEM,
|
||||
ERR_EXPECTED_PARAM_IMM,
|
||||
ERR_INCORRECT_BIN,
|
||||
ERR_INCORRECT_HEX,
|
||||
ERR_INCORRECT_DEC,
|
||||
ERR_LABEL_EXISTS,
|
||||
ERR_UNKNOWN_LABEL,
|
||||
ERR_NO_MATCHING_BRACKETS,
|
||||
ERR_EXT_CANT_EXTEND_OPCODE,
|
||||
ERR_EXT_PAR_NOT_EXT,
|
||||
ERR_WRONG_PARAMETER_ACC,
|
||||
ERR_WRONG_PARAMETER_MID_ACC,
|
||||
ERR_INVALID_REGISTER,
|
||||
ERR_OUT_RANGE_NUMBER
|
||||
};
|
||||
|
||||
|
||||
// Unless you want labels to carry over between files, you probably
|
||||
// want to create a new DSPAssembler for every file you assemble.
|
||||
class DSPAssembler
|
||||
{
|
||||
public:
|
||||
DSPAssembler(const AssemblerSettings &settings);
|
||||
~DSPAssembler();
|
||||
|
||||
// line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
|
||||
// one for each word of code, indicating the source assembler code line number it came from.
|
||||
|
||||
// If returns false, call GetErrorString to get some text to present to the user.
|
||||
bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
|
||||
|
||||
std::string GetErrorString() const { return last_error_str; }
|
||||
err_t GetError() const { return last_error; }
|
||||
|
||||
private:
|
||||
struct param_t
|
||||
{
|
||||
u32 val;
|
||||
partype_t type;
|
||||
char *str;
|
||||
};
|
||||
|
||||
enum segment_t
|
||||
{
|
||||
SEGMENT_CODE = 0,
|
||||
SEGMENT_DATA,
|
||||
SEGMENT_OVERLAY,
|
||||
SEGMENT_MAX
|
||||
};
|
||||
|
||||
// Utility functions
|
||||
s32 ParseValue(const char *str);
|
||||
u32 ParseExpression(const char *ptr);
|
||||
|
||||
u32 GetParams(char *parstr, param_t *par);
|
||||
|
||||
void InitPass(int pass);
|
||||
bool AssembleFile(const char *fname, int pass);
|
||||
|
||||
void ShowError(err_t err_code, const char *extra_info = NULL);
|
||||
// void ShowWarning(err_t err_code, const char *extra_info = NULL);
|
||||
|
||||
char *FindBrackets(char *src, char *dst);
|
||||
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
|
||||
bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
|
||||
void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
|
||||
|
||||
char *gdg_buffer;
|
||||
|
||||
std::string include_dir;
|
||||
std::string cur_line;
|
||||
|
||||
u32 m_cur_addr;
|
||||
int m_totalSize;
|
||||
u8 m_cur_pass;
|
||||
|
||||
LabelMap labels;
|
||||
|
||||
u32 code_line;
|
||||
bool failed;
|
||||
std::string last_error_str;
|
||||
err_t last_error;
|
||||
|
||||
typedef std::map<std::string, std::string> AliasMap;
|
||||
AliasMap aliases;
|
||||
|
||||
segment_t cur_segment;
|
||||
u32 segment_addr[SEGMENT_MAX];
|
||||
int m_current_param;
|
||||
const AssemblerSettings settings_;
|
||||
};
|
||||
|
||||
#endif // _DSP_ASSEMBLE_H
|
||||
|
Reference in New Issue
Block a user