summaryrefslogtreecommitdiff
path: root/Source/UnitTests/Core
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2022-06-22 14:26:50 +0200
committerGitHub <noreply@github.com>2022-06-22 14:26:50 +0200
commitceef02ed2a861b636ed1f887a50faf01afe136dd (patch)
treef97e2b604f2cad535bd6962c0753adfd1b519348 /Source/UnitTests/Core
parentefcb9bec9cd20a276204015d5cc73ecd1dab9c5f (diff)
parentdec48ed7de1e9710dc2aad5690e3a32b8ee8ed13 (diff)
Merge pull request #10750 from Pokechu22/hermes-test
Enhance DSPAssemblyTest, and fix various DSPTool bugs discovered while doing so
Diffstat (limited to 'Source/UnitTests/Core')
-rw-r--r--Source/UnitTests/Core/CMakeLists.txt1
-rw-r--r--Source/UnitTests/Core/DSP/DSPAssemblyTest.cpp81
-rw-r--r--Source/UnitTests/Core/DSP/DSPTestText.cpp6
-rw-r--r--Source/UnitTests/Core/DSP/HermesBinary.cpp12
-rw-r--r--Source/UnitTests/Core/DSP/HermesText.cpp (renamed from Source/UnitTests/Core/DSP/hermes.s)24
-rw-r--r--Source/UnitTests/Core/DSP/HermesText.h8
-rw-r--r--Source/UnitTests/Core/PageFaultTest.cpp20
7 files changed, 108 insertions, 44 deletions
diff --git a/Source/UnitTests/Core/CMakeLists.txt b/Source/UnitTests/Core/CMakeLists.txt
index 134f7da78b..1e24489239 100644
--- a/Source/UnitTests/Core/CMakeLists.txt
+++ b/Source/UnitTests/Core/CMakeLists.txt
@@ -8,6 +8,7 @@ add_dolphin_test(DSPAssemblyTest
DSP/DSPTestBinary.cpp
DSP/DSPTestText.cpp
DSP/HermesBinary.cpp
+ DSP/HermesText.cpp
)
add_dolphin_test(ESFormatsTest IOS/ES/FormatsTest.cpp)
diff --git a/Source/UnitTests/Core/DSP/DSPAssemblyTest.cpp b/Source/UnitTests/Core/DSP/DSPAssemblyTest.cpp
index dd3c96e194..44e4cde30e 100644
--- a/Source/UnitTests/Core/DSP/DSPAssemblyTest.cpp
+++ b/Source/UnitTests/Core/DSP/DSPAssemblyTest.cpp
@@ -1,17 +1,19 @@
// Copyright 2017 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "Common/FileUtil.h"
+#include <fmt/format.h>
+
#include "Core/DSP/DSPCodeUtil.h"
#include "Core/DSP/DSPDisassembler.h"
#include "DSPTestBinary.h"
#include "DSPTestText.h"
#include "HermesBinary.h"
+#include "HermesText.h"
#include <gtest/gtest.h>
-static bool RoundTrippableDissassemble(const std::vector<u16>& code, std::string& text)
+static bool RoundTrippableDisassemble(const std::vector<u16>& code, std::string& text)
{
DSP::AssemblerSettings settings;
settings.ext_separator = '\'';
@@ -31,20 +33,20 @@ static bool RoundTrip(const std::vector<u16>& code1)
{
std::vector<u16> code2;
std::string text;
- if (!RoundTrippableDissassemble(code1, text))
+ if (!RoundTrippableDisassemble(code1, text))
{
- printf("RoundTrip: Disassembly failed.\n");
+ fmt::print("RoundTrip: Disassembly failed.\n");
return false;
}
if (!DSP::Assemble(text, code2))
{
- printf("RoundTrip: Assembly failed.\n");
+ fmt::print("RoundTrip: Assembly failed.\n");
return false;
}
if (!DSP::Compare(code1, code2))
{
- DSP::Disassemble(code1, true, text);
- printf("%s", text.c_str());
+ fmt::print("RoundTrip: Assembled code does not match input code\n");
+ return false;
}
return true;
}
@@ -57,25 +59,54 @@ static bool SuperTrip(const char* asm_code)
std::string text;
if (!DSP::Assemble(asm_code, code1))
{
- printf("SuperTrip: First assembly failed\n");
+ fmt::print("SuperTrip: First assembly failed\n");
return false;
}
- printf("First assembly: %i words\n", (int)code1.size());
+ fmt::print("First assembly: {} words\n", code1.size());
- if (!RoundTrippableDissassemble(code1, text))
+ if (!RoundTrippableDisassemble(code1, text))
{
- printf("SuperTrip: Disassembly failed\n");
+ fmt::print("SuperTrip: Disassembly failed\n");
return false;
}
else
{
- printf("Disassembly:\n");
- printf("%s", text.c_str());
+ fmt::print("Disassembly:\n");
+ fmt::print("{}", text);
}
if (!DSP::Assemble(text, code2))
{
- printf("SuperTrip: Second assembly failed\n");
+ fmt::print("SuperTrip: Second assembly failed\n");
+ return false;
+ }
+
+ if (!DSP::Compare(code1, code2))
+ {
+ fmt::print("SuperTrip: Assembled code does not match between passes\n");
+ return false;
+ }
+ return true;
+}
+
+// Assembles asm_code, and verifies that it matches code1.
+static bool AssembleAndCompare(const char* asm_code, const std::vector<u16>& code1)
+{
+ std::vector<u16> code2;
+ if (!DSP::Assemble(asm_code, code2))
+ {
+ fmt::print("AssembleAndCompare: Assembly failed\n");
+ return false;
+ }
+
+ fmt::print("AssembleAndCompare: Produced {} words; padding to {} words\n", code2.size(),
+ code1.size());
+ while (code2.size() < code1.size())
+ code2.push_back(0);
+
+ if (!DSP::Compare(code1, code2))
+ {
+ fmt::print("AssembleAndCompare: Assembled code does not match expected code\n");
return false;
}
return true;
@@ -129,11 +160,21 @@ TEST(DSPAssembly, ExtendedInstructions)
" ADDAXL'MV $ACC1, $AX1.L : $AX1.H, $AC1.M\n"));
}
+TEST(DSPAssembly, HermesText)
+{
+ ASSERT_TRUE(SuperTrip(s_hermes_text));
+}
+
TEST(DSPAssembly, HermesBinary)
{
ASSERT_TRUE(RoundTrip(s_hermes_bin));
}
+TEST(DSPAssembly, HermesAssemble)
+{
+ ASSERT_TRUE(AssembleAndCompare(s_hermes_text, s_hermes_bin));
+}
+
TEST(DSPAssembly, DSPTestText)
{
ASSERT_TRUE(SuperTrip(s_dsp_test_text));
@@ -144,11 +185,7 @@ 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.
-*/
+TEST(DSPAssembly, DSPTestAssemble)
+{
+ ASSERT_TRUE(AssembleAndCompare(s_dsp_test_text, s_dsp_test_bin));
+}
diff --git a/Source/UnitTests/Core/DSP/DSPTestText.cpp b/Source/UnitTests/Core/DSP/DSPTestText.cpp
index 2e1f60a450..bc02ef1ba2 100644
--- a/Source/UnitTests/Core/DSP/DSPTestText.cpp
+++ b/Source/UnitTests/Core/DSP/DSPTestText.cpp
@@ -89,7 +89,7 @@ MEM_LO: equ 0x0f7F
CW 0x1305
CW 0x1306
- s40
+ s16
lri $r12, #0x00ff
main:
@@ -469,7 +469,7 @@ irq4:
jmp irq
irq5:
; jmp finale
- s40
+ s16
mrr $r0d, $r1c
mrr $r0d, $r1e
clr $acc0
@@ -609,7 +609,7 @@ dma_copy:
ret
-send_back_16:
+send_back_40:
cw 0x8e00
call send_back
diff --git a/Source/UnitTests/Core/DSP/HermesBinary.cpp b/Source/UnitTests/Core/DSP/HermesBinary.cpp
index 299f50e16c..a7f485d0a0 100644
--- a/Source/UnitTests/Core/DSP/HermesBinary.cpp
+++ b/Source/UnitTests/Core/DSP/HermesBinary.cpp
@@ -1,5 +1,13 @@
-// Copyright 2017 Dolphin Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* DSP_MIXER -> PCM VOICE SOFTWARE PROCESSOR (8-16 Bits Mono/Stereo Voices)
+
+// Thanks to Duddie for you hard work and documentation
+
+Copyright (c) 2008 Hermes <www.entuwii.net>
+All rights reserved.
+
+SPDX-License-Identifier: BSD-3-Clause
+
+*/
#include "HermesBinary.h"
diff --git a/Source/UnitTests/Core/DSP/hermes.s b/Source/UnitTests/Core/DSP/HermesText.cpp
index d5418a578a..f7f83a9737 100644
--- a/Source/UnitTests/Core/DSP/hermes.s
+++ b/Source/UnitTests/Core/DSP/HermesText.cpp
@@ -9,7 +9,9 @@ SPDX-License-Identifier: BSD-3-Clause
*/
+#include "HermesText.h"
+const char s_hermes_text[21370] = R"(
/********************************/
/** REGISTER NAMES **/
/********************************/
@@ -173,7 +175,7 @@ MEM_SND: equ data_end ; it need 2048 words (4096 bytes)
lri $CONFIG, #0xff
lri $SR,#0
- s40
+ s16
clr15
m0
@@ -254,7 +256,7 @@ sys_command:
jmp recv_cmd
run_nexttask:
- s40
+ s16
call wait_for_cpu_mail
lrs $29,@CMBL
call wait_for_cpu_mail
@@ -542,7 +544,11 @@ no_delay:
/////////////////////////////////////
// end of delay time section
/////////////////////////////////////
-
+)" // Work around C2026 on MSVC, which allows at most 16380 single-byte characters in a single
+ // non-concatenated string literal (but you can concatenate multiple shorter string literals to
+ // produce a longer string just fine). (This comment is not part of the actual test program,
+ // and instead there is a single blank line at this location.)
+ R"(
/* bucle de generacion de samples */
@@ -655,7 +661,7 @@ left_skip2:
cmp
- jrl $AR0 //get_sample or get_sample2 method
+ jrnc $AR0 //get_sample or get_sample2 method
sr @COUNTERH_SMP, $ACH1
sr @COUNTERL_SMP, $ACM1
@@ -711,7 +717,7 @@ get_sample2: // slow method
// if addr>addr end get a new buffer (if you uses double buffer)
- jge get_new_buffer
+ jc get_new_buffer
// load samples from dma, return $ar2 with the addr to get the samples and return using $ar0 to the routine to process 8-16bits Mono/Stereo
@@ -741,7 +747,7 @@ get_sample: // fast method
// compares if the current address is >= end address to change the buffer or stops
cmp
- jge get_new_buffer
+ jc get_new_buffer
// load the new sample from the buffer
@@ -961,8 +967,8 @@ wait_dma:
wait_for_dsp_mail:
lrs $ACM1, @DMBH
- andf $ACM1, #0x8000
- jnz wait_for_dsp_mail
+ andcf $ACM1, #0x8000
+ jlz wait_for_dsp_mail
ret
wait_for_cpu_mail:
@@ -1077,4 +1083,4 @@ polla_loca:
clr $ACC0
jmp recv_cmd
-
+)";
diff --git a/Source/UnitTests/Core/DSP/HermesText.h b/Source/UnitTests/Core/DSP/HermesText.h
new file mode 100644
index 0000000000..99c16686e2
--- /dev/null
+++ b/Source/UnitTests/Core/DSP/HermesText.h
@@ -0,0 +1,8 @@
+// Copyright 2022 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <string>
+
+extern const char s_hermes_text[21370];
diff --git a/Source/UnitTests/Core/PageFaultTest.cpp b/Source/UnitTests/Core/PageFaultTest.cpp
index e340ca7646..e873a28e73 100644
--- a/Source/UnitTests/Core/PageFaultTest.cpp
+++ b/Source/UnitTests/Core/PageFaultTest.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <chrono>
+#include <fmt/format.h>
#include "Common/CommonTypes.h"
#include "Common/Timer.h"
@@ -79,16 +80,19 @@ TEST(PageFault, PageFault)
perform_invalid_access(data);
auto end = std::chrono::high_resolution_clock::now();
-#define AS_NS(diff) \
- ((unsigned long long)std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count())
+ auto difference_in_nanoseconds = [](auto start, auto end) {
+ return std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
+ };
EMM::UninstallExceptionHandler();
JitInterface::SetJit(nullptr);
- printf("page fault timing:\n");
- printf("start->HandleFault %llu ns\n", AS_NS(pfjit.m_pre_unprotect_time - start));
- printf("UnWriteProtectMemory %llu ns\n",
- AS_NS(pfjit.m_post_unprotect_time - pfjit.m_pre_unprotect_time));
- printf("HandleFault->end %llu ns\n", AS_NS(end - pfjit.m_post_unprotect_time));
- printf("total %llu ns\n", AS_NS(end - start));
+ fmt::print("page fault timing:\n");
+ fmt::print("start->HandleFault {} ns\n",
+ difference_in_nanoseconds(start, pfjit.m_pre_unprotect_time));
+ fmt::print("UnWriteProtectMemory {} ns\n",
+ difference_in_nanoseconds(pfjit.m_pre_unprotect_time, pfjit.m_post_unprotect_time));
+ fmt::print("HandleFault->end {} ns\n",
+ difference_in_nanoseconds(pfjit.m_post_unprotect_time, end));
+ fmt::print("total {} ns\n", difference_in_nanoseconds(start, end));
}