mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
e149ad4f0a
SPDX standardizes how source code conveys its copyright and licensing information. See https://spdx.github.io/spdx-spec/1-rationale/ . SPDX tags are adopted in many large projects, including things like the Linux kernel.
155 lines
3.9 KiB
C++
155 lines
3.9 KiB
C++
// Copyright 2017 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "Common/FileUtil.h"
|
|
#include "Core/DSP/DSPCodeUtil.h"
|
|
#include "Core/DSP/DSPDisassembler.h"
|
|
|
|
#include "DSPTestBinary.h"
|
|
#include "DSPTestText.h"
|
|
#include "HermesBinary.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
static bool RoundTrippableDissassemble(const std::vector<u16>& code, std::string& text)
|
|
{
|
|
DSP::AssemblerSettings settings;
|
|
settings.ext_separator = '\'';
|
|
settings.decode_names = true;
|
|
settings.decode_registers = true;
|
|
// These two prevent roundtripping.
|
|
settings.show_hex = false;
|
|
settings.show_pc = false;
|
|
DSP::DSPDisassembler disasm(settings);
|
|
|
|
return disasm.Disassemble(code, text);
|
|
}
|
|
|
|
// This test goes from text ASM to binary to text ASM and once again back to binary.
|
|
// Then the two binaries are compared.
|
|
static bool RoundTrip(const std::vector<u16>& code1)
|
|
{
|
|
std::vector<u16> code2;
|
|
std::string text;
|
|
if (!RoundTrippableDissassemble(code1, text))
|
|
{
|
|
printf("RoundTrip: Disassembly failed.\n");
|
|
return false;
|
|
}
|
|
if (!DSP::Assemble(text, code2))
|
|
{
|
|
printf("RoundTrip: Assembly failed.\n");
|
|
return false;
|
|
}
|
|
if (!DSP::Compare(code1, code2))
|
|
{
|
|
DSP::Disassemble(code1, true, text);
|
|
printf("%s", text.c_str());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// This test goes from text ASM to binary to text ASM and once again back to binary.
|
|
// Very convenient for testing. Then the two binaries are compared.
|
|
static bool SuperTrip(const char* asm_code)
|
|
{
|
|
std::vector<u16> code1, code2;
|
|
std::string text;
|
|
if (!DSP::Assemble(asm_code, code1))
|
|
{
|
|
printf("SuperTrip: First assembly failed\n");
|
|
return false;
|
|
}
|
|
printf("First assembly: %i words\n", (int)code1.size());
|
|
|
|
if (!RoundTrippableDissassemble(code1, text))
|
|
{
|
|
printf("SuperTrip: Disassembly failed\n");
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
printf("Disassembly:\n");
|
|
printf("%s", text.c_str());
|
|
}
|
|
|
|
if (!DSP::Assemble(text, code2))
|
|
{
|
|
printf("SuperTrip: Second assembly failed\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Let's start out easy - a trivial instruction..
|
|
TEST(DSPAssembly, TrivialInstruction)
|
|
{
|
|
ASSERT_TRUE(SuperTrip(" NOP\n"));
|
|
}
|
|
|
|
// Now let's do several.
|
|
TEST(DSPAssembly, SeveralTrivialInstructions)
|
|
{
|
|
ASSERT_TRUE(SuperTrip(" NOP\n"
|
|
" NOP\n"
|
|
" NOP\n"));
|
|
}
|
|
|
|
// Turning it up a notch.
|
|
TEST(DSPAssembly, SeveralNoParameterInstructions)
|
|
{
|
|
ASSERT_TRUE(SuperTrip(" SET16\n"
|
|
" SET40\n"
|
|
" CLR15\n"
|
|
" M0\n"
|
|
" M2\n"));
|
|
}
|
|
|
|
// Time to try labels and parameters, and comments.
|
|
TEST(DSPAssembly, LabelsParametersAndComments)
|
|
{
|
|
ASSERT_TRUE(SuperTrip("DIRQ_TEST: equ 0xfffb ; DSP Irq Request\n"
|
|
" si @0xfffc, #0x8888\n"
|
|
" si @0xfffd, #0xbeef\n"
|
|
" si @DIRQ_TEST, #0x0001\n"));
|
|
}
|
|
|
|
// Let's see if registers roundtrip. Also try predefined labels.
|
|
TEST(DSPAssembly, RegistersAndPredefinedLabels)
|
|
{
|
|
ASSERT_TRUE(SuperTrip(" si @0xfffc, #0x8888\n"
|
|
" si @0xfffd, #0xbeef\n"
|
|
" si @DIRQ, #0x0001\n"));
|
|
}
|
|
|
|
// Let's try some messy extended instructions.
|
|
TEST(DSPAssembly, ExtendedInstructions)
|
|
{
|
|
ASSERT_TRUE(SuperTrip(" MULMV'SN $AX0.L, $AX0.H, $ACC0 : @$AR2, $AC1.M\n"
|
|
" ADDAXL'MV $ACC1, $AX1.L : $AX1.H, $AC1.M\n"));
|
|
}
|
|
|
|
TEST(DSPAssembly, HermesBinary)
|
|
{
|
|
ASSERT_TRUE(RoundTrip(s_hermes_bin));
|
|
}
|
|
|
|
TEST(DSPAssembly, DSPTestText)
|
|
{
|
|
ASSERT_TRUE(SuperTrip(s_dsp_test_text));
|
|
}
|
|
|
|
TEST(DSPAssembly, DSPTestBinary)
|
|
{
|
|
ASSERT_TRUE(RoundTrip(s_dsp_test_bin));
|
|
}
|
|
|
|
/*
|
|
|
|
if (File::ReadFileToString("C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test))
|
|
SuperTrip(dsp_test.c_str());
|
|
|
|
//.File::ReadFileToString("C:/devkitPro/trunk/libogc/libasnd/dsp_mixer/dsp_mixer.s", &dsp_test);
|
|
// This is CLOSE to working. Sorry about the local path btw. This is preliminary code.
|
|
*/
|