diff options
| author | Soren Jorvang <soren.jorvang@gmail.com> | 2011-01-29 14:06:48 +0000 |
|---|---|---|
| committer | Soren Jorvang <soren.jorvang@gmail.com> | 2011-01-29 14:06:48 +0000 |
| commit | b3a183dffefc1cb1701ee2a8a2cbe0080774aced (patch) | |
| tree | aeb7b14894e6b17dc70f2bb71e28d1c3f6156f09 /Source/Core/DSPCore | |
| parent | 10675ba3c02295cb61f785840ac75e8e65cfb549 (diff) | |
Core and DSPCore now have mutual dependencies, which breaks the
assumption on the part of many linkers that static libraries make
up a DAG, so merge libdspcore into libcore.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6967 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/DSPCore')
54 files changed, 0 insertions, 16904 deletions
diff --git a/Source/Core/DSPCore/CMakeLists.txt b/Source/Core/DSPCore/CMakeLists.txt deleted file mode 100644 index ab379cd377..0000000000 --- a/Source/Core/DSPCore/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -set(SRCS Src/assemble.cpp - Src/disassemble.cpp - Src/DSPAccelerator.cpp - Src/DSPIntCCUtil.cpp - Src/DSPIntExtOps.cpp - Src/DSPHWInterface.cpp - Src/DSPMemoryMap.cpp - Src/DSPStacks.cpp - Src/DSPAnalyzer.cpp - Src/DspIntArithmetic.cpp - Src/DspIntBranch.cpp - Src/DspIntLoadStore.cpp - Src/DspIntMisc.cpp - Src/DspIntMultiplier.cpp - Src/DSPEmitter.cpp - Src/DSPCodeUtil.cpp - Src/LabelMap.cpp - Src/DSPInterpreter.cpp - Src/DSPCore.cpp - Src/DSPTables.cpp - Src/Jit/DSPJitRegCache.cpp - Src/Jit/DSPJitExtOps.cpp - Src/Jit/DSPJitBranch.cpp - Src/Jit/DSPJitCCUtil.cpp - Src/Jit/DSPJitArithmetic.cpp - Src/Jit/DSPJitLoadStore.cpp - Src/Jit/DSPJitMultiplier.cpp - Src/Jit/DSPJitUtil.cpp - Src/Jit/DSPJitMisc.cpp) - -add_library(dspcore STATIC ${SRCS}) -target_link_libraries(dspcore core) -if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - add_definitions(-fPIC) -endif() diff --git a/Source/Core/DSPCore/DSPCore.vcproj b/Source/Core/DSPCore/DSPCore.vcproj deleted file mode 100644 index 43f7401e8a..0000000000 --- a/Source/Core/DSPCore/DSPCore.vcproj +++ /dev/null @@ -1,621 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="DSPCore" - ProjectGUID="{838A89A3-3AA0-4A45-ACBE-3D1E0980C2ED}" - RootNamespace="DSPCore" - Keyword="Win32Proj" - TargetFrameworkVersion="196613" - > - <Platforms> - <Platform - Name="Win32" - /> - <Platform - Name="x64" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="..\Common\Src" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="1" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug|x64" - OutputDirectory="$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="3" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="..\Common\Src" - PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="1" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="..\Common\Src" - PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|x64" - OutputDirectory="$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="3" - /> - <Tool - Name="VCCLCompilerTool" - AdditionalOptions="/MP" - Optimization="2" - EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="..\Common\Src" - PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="DebugFast|Win32" - OutputDirectory="$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="..\Common\Src" - PreprocessorDefinitions="DEBUGFAST;WIN32;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="DebugFast|x64" - OutputDirectory="$(PlatformName)\$(ConfigurationName)" - IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" - ConfigurationType="4" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - TargetEnvironment="3" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="..\Common\Src" - PreprocessorDefinitions="DEBUGFAST;WIN32;_LIB;_WINDOWS;NOPCH;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" - UsePrecompiledHeader="0" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="Interpreter" - > - <File - RelativePath=".\Src\DspIntArithmetic.cpp" - > - </File> - <File - RelativePath=".\Src\DspIntBranch.cpp" - > - </File> - <File - RelativePath=".\Src\DSPIntCCUtil.cpp" - > - </File> - <File - RelativePath=".\Src\DSPIntCCUtil.h" - > - </File> - <File - RelativePath=".\Src\DSPIntExtOps.cpp" - > - </File> - <File - RelativePath=".\Src\DSPIntExtOps.h" - > - </File> - <File - RelativePath=".\Src\DspIntLoadStore.cpp" - > - </File> - <File - RelativePath=".\Src\DspIntMisc.cpp" - > - </File> - <File - RelativePath=".\Src\DspIntMultiplier.cpp" - > - </File> - <File - RelativePath=".\Src\DSPIntUtil.h" - > - </File> - </Filter> - <Filter - Name="JIT" - > - <File - RelativePath=".\Src\DSPEmitter.cpp" - > - </File> - <File - RelativePath=".\Src\DSPEmitter.h" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitArithmetic.cpp" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitLoadStore.cpp" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitCCUtil.cpp" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitExtOps.cpp" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitBranch.cpp" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitMisc.cpp" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitMultiplier.cpp" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitRegCache.cpp" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitRegCache.h" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitUtil.cpp" - > - </File> - <File - RelativePath=".\Src\Jit\DSPJitUtil.h" - > - </File> - </Filter> - <File - RelativePath=".\Src\assemble.cpp" - > - </File> - <File - RelativePath=".\Src\assemble.h" - > - </File> - <File - RelativePath=".\Src\disassemble.cpp" - > - </File> - <File - RelativePath=".\Src\disassemble.h" - > - </File> - <File - RelativePath=".\Src\DSPAccelerator.cpp" - > - </File> - <File - RelativePath=".\Src\DSPAccelerator.h" - > - </File> - <File - RelativePath=".\Src\DSPAnalyzer.cpp" - > - </File> - <File - RelativePath=".\Src\DSPAnalyzer.h" - > - </File> - <File - RelativePath=".\Src\DSPBreakpoints.h" - > - </File> - <File - RelativePath=".\Src\DSPCodeUtil.cpp" - > - </File> - <File - RelativePath=".\Src\DSPCodeUtil.h" - > - </File> - <File - RelativePath=".\Src\DSPCommon.h" - > - </File> - <File - RelativePath=".\Src\DSPCore.cpp" - > - </File> - <File - RelativePath=".\Src\DSPCore.h" - > - </File> - <File - RelativePath=".\Src\DSPHost.h" - > - </File> - <File - RelativePath=".\Src\DSPHWInterface.cpp" - > - </File> - <File - RelativePath=".\Src\DSPHWInterface.h" - > - </File> - <File - RelativePath=".\Src\DSPInterpreter.cpp" - > - </File> - <File - RelativePath=".\Src\DSPInterpreter.h" - > - </File> - <File - RelativePath=".\Src\DSPMemoryMap.cpp" - > - </File> - <File - RelativePath=".\Src\DSPMemoryMap.h" - > - </File> - <File - RelativePath=".\Src\DSPStacks.cpp" - > - </File> - <File - RelativePath=".\Src\DSPStacks.h" - > - </File> - <File - RelativePath=".\Src\DSPTables.cpp" - > - </File> - <File - RelativePath=".\Src\DSPTables.h" - > - </File> - <File - RelativePath=".\Src\LabelMap.cpp" - > - </File> - <File - RelativePath=".\Src\LabelMap.h" - > - </File> - <File - RelativePath=".\Src\SConscript" - > - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/Source/Core/DSPCore/DSPCore.vcxproj b/Source/Core/DSPCore/DSPCore.vcxproj deleted file mode 100644 index 77eeeea1f3..0000000000 --- a/Source/Core/DSPCore/DSPCore.vcxproj +++ /dev/null @@ -1,239 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="DebugFast|Win32"> - <Configuration>DebugFast</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="DebugFast|x64"> - <Configuration>DebugFast</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <ItemGroup> - <ClCompile Include="Src\assemble.cpp" /> - <ClCompile Include="Src\disassemble.cpp" /> - <ClCompile Include="Src\DSPAccelerator.cpp" /> - <ClCompile Include="Src\DSPAnalyzer.cpp" /> - <ClCompile Include="Src\DSPCodeUtil.cpp" /> - <ClCompile Include="Src\DSPCore.cpp" /> - <ClCompile Include="Src\DSPEmitter.cpp" /> - <ClCompile Include="Src\DSPHWInterface.cpp" /> - <ClCompile Include="Src\DspIntArithmetic.cpp" /> - <ClCompile Include="Src\DspIntBranch.cpp" /> - <ClCompile Include="Src\DSPIntCCUtil.cpp" /> - <ClCompile Include="Src\DSPInterpreter.cpp" /> - <ClCompile Include="Src\DSPIntExtOps.cpp" /> - <ClCompile Include="Src\DspIntLoadStore.cpp" /> - <ClCompile Include="Src\DspIntMisc.cpp" /> - <ClCompile Include="Src\DspIntMultiplier.cpp" /> - <ClCompile Include="Src\DSPMemoryMap.cpp" /> - <ClCompile Include="Src\DSPStacks.cpp" /> - <ClCompile Include="Src\DSPTables.cpp" /> - <ClCompile Include="Src\Jit\DSPJitArithmetic.cpp" /> - <ClCompile Include="Src\Jit\DSPJitBranch.cpp" /> - <ClCompile Include="Src\Jit\DSPJitCCUtil.cpp" /> - <ClCompile Include="Src\Jit\DSPJitExtOps.cpp" /> - <ClCompile Include="Src\Jit\DSPJitLoadStore.cpp" /> - <ClCompile Include="Src\Jit\DSPJitMisc.cpp" /> - <ClCompile Include="Src\Jit\DSPJitMultiplier.cpp" /> - <ClCompile Include="Src\Jit\DSPJitRegCache.cpp" /> - <ClCompile Include="Src\Jit\DSPJitUtil.cpp" /> - <ClCompile Include="Src\LabelMap.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="Src\assemble.h" /> - <ClInclude Include="Src\disassemble.h" /> - <ClInclude Include="Src\DSPAccelerator.h" /> - <ClInclude Include="Src\DSPAnalyzer.h" /> - <ClInclude Include="Src\DSPBreakpoints.h" /> - <ClInclude Include="Src\DSPCodeUtil.h" /> - <ClInclude Include="Src\DSPCommon.h" /> - <ClInclude Include="Src\DSPCore.h" /> - <ClInclude Include="Src\DSPEmitter.h" /> - <ClInclude Include="Src\DSPHost.h" /> - <ClInclude Include="Src\DSPHWInterface.h" /> - <ClInclude Include="Src\DSPIntCCUtil.h" /> - <ClInclude Include="Src\DSPInterpreter.h" /> - <ClInclude Include="Src\DSPIntExtOps.h" /> - <ClInclude Include="Src\DSPIntUtil.h" /> - <ClInclude Include="Src\DSPMemoryMap.h" /> - <ClInclude Include="Src\DSPStacks.h" /> - <ClInclude Include="Src\DSPTables.h" /> - <ClInclude Include="Src\Jit\DSPJitRegCache.h" /> - <ClInclude Include="Src\Jit\DSPJitUtil.h" /> - <ClInclude Include="Src\LabelMap.h" /> - </ItemGroup> - <ItemGroup> - <None Include="Src\SConscript" /> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{4ED3C8BE-91A7-4361-8D46-16D03B678D4C}</ProjectGuid> - <RootNamespace>DSPCore</RootNamespace> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>StaticLibrary</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> - <ConfigurationType>StaticLibrary</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>StaticLibrary</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration"> - <ConfigurationType>StaticLibrary</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> - <ConfigurationType>StaticLibrary</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration"> - <ConfigurationType>StaticLibrary</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup /> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <AdditionalIncludeDirectories>..\Common\Src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <AdditionalIncludeDirectories>..\Common\Src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <AdditionalIncludeDirectories>..\Common\Src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <AdditionalIncludeDirectories>..\Common\Src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>DEBUGFAST;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <AdditionalIncludeDirectories>..\Common\Src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <AdditionalIncludeDirectories>..\Common\Src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>DEBUGFAST;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - </Link> - </ItemDefinitionGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project>
\ No newline at end of file diff --git a/Source/Core/DSPCore/Src/DSPAccelerator.cpp b/Source/Core/DSPCore/Src/DSPAccelerator.cpp deleted file mode 100644 index a45ab15e9d..0000000000 --- a/Source/Core/DSPCore/Src/DSPAccelerator.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (C) 2003 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 "Common.h" - -#include "DSPCore.h" -#include "DSPHost.h" -#include "DSPHWInterface.h" -#include "DSPInterpreter.h" - -// The hardware adpcm decoder :) -static s16 ADPCM_Step(u32& _rSamplePos) -{ - const s16 *pCoefTable = (const s16 *)&g_dsp.ifx_regs[DSP_COEF_A1_0]; - - if (((_rSamplePos) & 15) == 0) - { - g_dsp.ifx_regs[DSP_PRED_SCALE] = DSPHost_ReadHostMemory((_rSamplePos & ~15) >> 1); - _rSamplePos += 2; - } - - int scale = 1 << (g_dsp.ifx_regs[DSP_PRED_SCALE] & 0xF); - int coef_idx = (g_dsp.ifx_regs[DSP_PRED_SCALE] >> 4) & 0x7; - - s32 coef1 = pCoefTable[coef_idx * 2 + 0]; - s32 coef2 = pCoefTable[coef_idx * 2 + 1]; - - int temp = (_rSamplePos & 1) ? - (DSPHost_ReadHostMemory(_rSamplePos >> 1) & 0xF) : - (DSPHost_ReadHostMemory(_rSamplePos >> 1) >> 4); - - if (temp >= 8) - temp -= 16; - - // 0x400 = 0.5 in 11-bit fixed point - int val = (scale * temp) + ((0x400 + coef1 * (s16)g_dsp.ifx_regs[DSP_YN1] + coef2 * (s16)g_dsp.ifx_regs[DSP_YN2]) >> 11); - - // Clamp values. - if (val > 0x7FFF) - val = 0x7FFF; - else if (val < -0x7FFF) - val = -0x7FFF; - - g_dsp.ifx_regs[DSP_YN2] = g_dsp.ifx_regs[DSP_YN1]; - g_dsp.ifx_regs[DSP_YN1] = val; - - _rSamplePos++; - - // The advanced interpolation (linear, polyphase,...) is done by the UCode, - // so we don't need to bother with it here. - return val; -} - -u16 dsp_read_aram_d3() -{ - // Zelda ucode reads ARAM through 0xffd3. - const u32 EndAddress = (g_dsp.ifx_regs[DSP_ACEAH] << 16) | g_dsp.ifx_regs[DSP_ACEAL]; - u32 Address = (g_dsp.ifx_regs[DSP_ACCAH] << 16) | g_dsp.ifx_regs[DSP_ACCAL]; - u16 val = 0; - - switch (g_dsp.ifx_regs[DSP_FORMAT]) { - case 0x5: // u8 reads - val = DSPHost_ReadHostMemory(Address); - Address++; - break; - case 0x6: // u16 reads - val = (DSPHost_ReadHostMemory(Address*2) << 8) | DSPHost_ReadHostMemory(Address*2 + 1); - Address++; - break; - default: - ERROR_LOG(DSPLLE, "dsp_read_aram_d3() - unknown format 0x%x", g_dsp.ifx_regs[DSP_FORMAT]); - break; - } - - if (Address >= EndAddress) - { - // Set address back to start address. (never seen this here!) - Address = (g_dsp.ifx_regs[DSP_ACSAH] << 16) | g_dsp.ifx_regs[DSP_ACSAL]; - } - - g_dsp.ifx_regs[DSP_ACCAH] = Address >> 16; - g_dsp.ifx_regs[DSP_ACCAL] = Address & 0xffff; - return val; -} - -void dsp_write_aram_d3(u16 value) -{ - // Zelda ucode writes a bunch of zeros to ARAM through d3 during - // initialization. Don't know if it ever does it later, too. - u32 Address = (g_dsp.ifx_regs[DSP_ACCAH] << 16) | g_dsp.ifx_regs[DSP_ACCAL]; - - switch (g_dsp.ifx_regs[DSP_FORMAT]) { - case 0xA: // u16 writes - DSPHost_WriteHostMemory(value >> 8, Address*2); - DSPHost_WriteHostMemory(value & 0xFF, Address*2 + 1); - Address++; - break; - default: - ERROR_LOG(DSPLLE, "dsp_write_aram_d3() - unknown format 0x%x", g_dsp.ifx_regs[DSP_FORMAT]); - break; - } - - g_dsp.ifx_regs[DSP_ACCAH] = Address >> 16; - g_dsp.ifx_regs[DSP_ACCAL] = Address & 0xffff; -} - -u16 dsp_read_accelerator() -{ - const u32 EndAddress = (g_dsp.ifx_regs[DSP_ACEAH] << 16) | g_dsp.ifx_regs[DSP_ACEAL]; - u32 Address = (g_dsp.ifx_regs[DSP_ACCAH] << 16) | g_dsp.ifx_regs[DSP_ACCAL]; - u16 val; - - // let's do the "hardware" decode DSP_FORMAT is interesting - the Zelda - // ucode seems to indicate that the bottom two bits specify the "read size" - // and the address multiplier. The bits above that may be things like sign - // extention and do/do not use ADPCM. It also remains to be figured out - // whether there's a difference between the usual accelerator "read - // address" and 0xd3. - switch (g_dsp.ifx_regs[DSP_FORMAT]) - { - case 0x00: // ADPCM audio - val = ADPCM_Step(Address); - break; - case 0x0A: // 16-bit PCM audio - val = (DSPHost_ReadHostMemory(Address*2) << 8) | DSPHost_ReadHostMemory(Address*2 + 1); - g_dsp.ifx_regs[DSP_YN2] = g_dsp.ifx_regs[DSP_YN1]; - g_dsp.ifx_regs[DSP_YN1] = val; - Address++; - break; - case 0x19: // 8-bit PCM audio - val = DSPHost_ReadHostMemory(Address) << 8; - g_dsp.ifx_regs[DSP_YN2] = g_dsp.ifx_regs[DSP_YN1]; - g_dsp.ifx_regs[DSP_YN1] = val; - Address++; - break; - default: - ERROR_LOG(DSPLLE, "dsp_read_accelerator() - unknown format 0x%x", g_dsp.ifx_regs[DSP_FORMAT]); - Address++; - val = 0; - break; - } - - // TODO: Take GAIN into account - // adpcm = 0, pcm8 = 0x100, pcm16 = 0x800 - // games using pcm8 : Phoenix Wright Ace Attorney (Wiiware), Megaman 9-10 (WiiWare) - // games using pcm16: gc sega games, ... - - // Check for loop. - // Somehow, YN1 and YN2 must be initialized with their "loop" values, - // so yeah, it seems likely that we should raise an exception to let - // the DSP program do that, at least if DSP_FORMAT == 0x0A. - if (Address >= EndAddress) - { - // Set address back to start address. - Address = (g_dsp.ifx_regs[DSP_ACSAH] << 16) | g_dsp.ifx_regs[DSP_ACSAL]; - DSPCore_SetException(EXP_ACCOV); - } - - g_dsp.ifx_regs[DSP_ACCAH] = Address >> 16; - g_dsp.ifx_regs[DSP_ACCAL] = Address & 0xffff; - return val; -} diff --git a/Source/Core/DSPCore/Src/DSPAccelerator.h b/Source/Core/DSPCore/Src/DSPAccelerator.h deleted file mode 100644 index a64516a036..0000000000 --- a/Source/Core/DSPCore/Src/DSPAccelerator.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2003 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_ACCELERATOR_H -#define _DSP_ACCELERATOR_H - -u16 dsp_read_accelerator(); - -u16 dsp_read_aram_d3(); -void dsp_write_aram_d3(u16 value); - -#endif diff --git a/Source/Core/DSPCore/Src/DSPAnalyzer.cpp b/Source/Core/DSPCore/Src/DSPAnalyzer.cpp deleted file mode 100644 index 8f6b0d4e35..0000000000 --- a/Source/Core/DSPCore/Src/DSPAnalyzer.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (C) 2003 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 8 -#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 - { 0x26fc, // lrs $AC0.M, @DMBH - 0x02a0, 0x8000, // andf $AC0.M, #0x8000 - 0x029c, 0xFFFF, // jlnz 0x???? - 0, 0 }, - { 0x27fc, // lrs $AC1.M, @DMBH - 0x03a0, 0x8000, // andf $AC1.M, #0x8000 - 0x029c, 0xFFFF, // jlnz 0x???? - 0, 0 }, - // From Zelda: - { 0x00de, 0xFFFE, // LR $AC0.M, @CMBH - 0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000 - 0x029c, 0xFFFF, // JLNZ 0x05cf - 0 }, - // From Zelda - experimental - { 0x00da, 0x0352, // lr $AX0.H, @0x0352 - 0x8600, // tstaxh $AX0.H - 0x0295, 0xFFFF, // jz 0x???? - 0, 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. - u16 last_arithmetic = 0; - for (int addr = start_addr; addr < end_addr;) - { - UDSPInstruction inst = dsp_imem_read(addr); - const DSPOPCTemplate *opcode = GetOpTemplate(inst); - if (!opcode) - { - addr++; - continue; - } - code_flags[addr] |= CODE_START_OF_INST; - // Look for loops. - if ((inst & 0xffe0) == 0x0060 || (inst & 0xff00) == 0x1100) - { - // BLOOP, BLOOPI - u16 loop_end = dsp_imem_read(addr + 1); - code_flags[addr] |= CODE_LOOP_START; - code_flags[loop_end] |= CODE_LOOP_END; - } - else if ((inst & 0xffe0) == 0x0040 || (inst & 0xff00) == 0x1000) - { - // LOOP, LOOPI - code_flags[addr] |= CODE_LOOP_START; - code_flags[addr + 1] |= CODE_LOOP_END; - } - - // Mark the last arithmetic/multiplier instruction before a branch. - // We must update the SR reg at these instructions - if (opcode->updates_sr) - { - last_arithmetic = addr; - } - - if (opcode->branch && !opcode->uncond_branch) - { - code_flags[last_arithmetic] |= CODE_UPDATE_SR; - } - - // If an instruction potentially raises exceptions, mark the following - // instruction as needing to check for exceptions - if (opcode->opcode == 0x00c0 || - opcode->opcode == 0x1800 || - opcode->opcode == 0x1880 || - opcode->opcode == 0x1900 || - opcode->opcode == 0x1980 || - opcode->opcode == 0x2000 || - opcode->extended - ) - code_flags[addr + opcode->size] |= CODE_CHECK_INT; - - addr += opcode->size; - } - - // Next, we'll scan for potential idle skips. - for (int s = 0; s < NUM_IDLE_SIGS; s++) - { - for (int addr = start_addr; addr < end_addr; addr++) - { - bool found = false; - for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++) - { - if (idle_skip_sigs[s][i] == 0) - found = true; - if (idle_skip_sigs[s][i] == 0xFFFF) - continue; - if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i)) - break; - } - if (found) - { - INFO_LOG(DSPLLE, "Idle skip location found at %02x (sigNum:%d)", addr, s+1); - code_flags[addr] |= CODE_IDLE_SKIP; - } - } - } - INFO_LOG(DSPLLE, "Finished analysis."); -} - -void Analyze() -{ - Reset(); - AnalyzeRange(0x0000, 0x1000); // IRAM - AnalyzeRange(0x8000, 0x9000); // IROM -} - -} // namespace diff --git a/Source/Core/DSPCore/Src/DSPAnalyzer.h b/Source/Core/DSPCore/Src/DSPAnalyzer.h deleted file mode 100644 index 9c05dae708..0000000000 --- a/Source/Core/DSPCore/Src/DSPAnalyzer.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2003 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_START = 4, - CODE_LOOP_END = 8, - CODE_UPDATE_SR = 16, - CODE_CHECK_INT = 32, -}; - -// 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 diff --git a/Source/Core/DSPCore/Src/DSPBreakpoints.h b/Source/Core/DSPCore/Src/DSPBreakpoints.h deleted file mode 100644 index b366e760a7..0000000000 --- a/Source/Core/DSPCore/Src/DSPBreakpoints.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2003 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 diff --git a/Source/Core/DSPCore/Src/DSPCodeUtil.cpp b/Source/Core/DSPCore/Src/DSPCodeUtil.cpp deleted file mode 100644 index ca9c01d5dc..0000000000 --- a/Source/Core/DSPCore/Src/DSPCodeUtil.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (C) 2003 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, bool force) -{ - AssemblerSettings settings; - // settings.pc = 0; - // settings.decode_registers = false; - // settings.decode_names = false; - settings.force = force; - // 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 = true; - settings.show_pc = line_numbers; - settings.ext_separator = '\''; - settings.decode_names = true; - 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_padded = code; - // Pad with nops to 32byte boundary - while (code_padded.size() & 0x7f) - code_padded.push_back(0); - - char buffer[1024]; - header.clear(); - header.reserve(code_padded.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("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n"); - - header.append("\t{\n\t\t"); - for (u32 j = 0; j < code_padded.size(); j++) - { - if (j && ((j & 15) == 0)) - header.append("\n\t\t"); - sprintf(buffer, "0x%04x, ", code_padded[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) -{ - std::vector<std::vector<u16> > codes_padded; - char buffer[1024]; - int reserveSize = 0; - for(int i = 0; i < numCodes; i++) - { - codes_padded.push_back(codes[i]); - // Pad with nops to 32byte boundary - while (codes_padded.at(i).size() & 0x7f) - codes_padded.at(i).push_back(0); - - reserveSize += (int)codes_padded.at(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("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n"); - - for(int i = 0; i < numCodes; i++) - { - if(codes[i].size() == 0) - continue; - - header.append("\t{\n\t\t"); - for (u32 j = 0; j < codes_padded.at(i).size(); j++) - { - if (j && ((j & 15) == 0)) - header.append("\n\t\t"); - sprintf(buffer, "0x%04x, ", codes_padded.at(i).at(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; -} diff --git a/Source/Core/DSPCore/Src/DSPCodeUtil.h b/Source/Core/DSPCore/Src/DSPCodeUtil.h deleted file mode 100644 index 2a2ebfb228..0000000000 --- a/Source/Core/DSPCore/Src/DSPCodeUtil.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2003 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 force = false); -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 diff --git a/Source/Core/DSPCore/Src/DSPCommon.h b/Source/Core/DSPCore/Src/DSPCommon.h deleted file mode 100644 index 8133cdc54e..0000000000 --- a/Source/Core/DSPCore/Src/DSPCommon.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __DSPCOMMON_H -#define __DSPCOMMON_H -#include "CommonTypes.h" -typedef u16 UDSPInstruction; - - - -#endif diff --git a/Source/Core/DSPCore/Src/DSPCore.cpp b/Source/Core/DSPCore/Src/DSPCore.cpp deleted file mode 100644 index b053395881..0000000000 --- a/Source/Core/DSPCore/Src/DSPCore.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/*==================================================================== - - 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 "Hash.h" -#include "Thread.h" -#include "DSPCore.h" -#include "DSPEmitter.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_STOP; -u16 cyclesLeft = 0; -DSPEmitter *dspjit = NULL; -Common::Event step_event; -Common::CriticalSection ExtIntCriticalSection; - -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) - { - fread(rom, 1, size_in_bytes, pFile); - fclose(pFile); - - // Byteswap the rom. - for (int i = 0; i < size_in_words; i++) - rom[i] = Common::swap16(rom[i]); - - // Always keep ROMs write protected. - WriteProtectMemory(rom, size_in_bytes, false); - return true; - } - - PanicAlertT("Failed to load DSP ROM: %s", fname); - return false; -} - -// Returns false iff the hash fails and the user hits "Yes" -static bool VerifyRoms(const char *irom_filename, const char *coef_filename) -{ - static const u32 hash[] = { 0x66f334fe, 0xf3b93527 }; - static const int size[] = { DSP_IROM_BYTE_SIZE, DSP_COEF_BYTE_SIZE }; - const u16 *data[] = { g_dsp.irom, g_dsp.coef }; - - for (int i = 0; i < 2; i++) - { - if (HashAdler32((u8*)data[i], size[i]) != hash[i]) - { - if (AskYesNoT("%s has an incorrect hash.\n" - "Would you like to stop now to fix the problem?\n" - "If you select \"No\", audio will be garbled.", - (i == 0) ? irom_filename : coef_filename)) - return false; - } - } - - return true; -} - -bool DSPCore_Init(const char *irom_filename, const char *coef_filename, - bool bUsingJIT) -{ - g_dsp.step_counter = 0; - cyclesLeft = 0; - dspjit = NULL; - - 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. - LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom); - LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef); - if (!VerifyRoms(irom_filename, coef_filename)) - return false; - - memset(&g_dsp.r,0,sizeof(g_dsp.r)); - - 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.wr[0] = 0xffff; - g_dsp.r.wr[1] = 0xffff; - g_dsp.r.wr[2] = 0xffff; - g_dsp.r.wr[3] = 0xffff; - - g_dsp.r.sr |= SR_INT_ENABLE; - g_dsp.r.sr |= SR_EXT_INT_ENABLE; - - 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); - - // Initialize JIT, if necessary - if(bUsingJIT) - dspjit = new DSPEmitter(); - - DSPAnalyzer::Analyze(); - - step_event.Init(); - - core_state = DSPCORE_RUNNING; - - return true; -} - -void DSPCore_Shutdown() -{ - core_state = DSPCORE_STOP; - - if(dspjit) { - delete dspjit; - dspjit = NULL; - } - 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() -{ - g_dsp.pc = DSP_RESET_VECTOR; - - g_dsp.r.wr[0] = 0xffff; - g_dsp.r.wr[1] = 0xffff; - g_dsp.r.wr[2] = 0xffff; - g_dsp.r.wr[3] = 0xffff; - -} - -void DSPCore_SetException(u8 level) -{ - g_dsp.exceptions |= 1 << level; -} - -// Notify that an external interrupt is pending (used by thread mode) -void DSPCore_SetExternalInterrupt(bool val) -{ - ExtIntCriticalSection.Enter(); - g_dsp.external_interrupt_waiting = val; - ExtIntCriticalSection.Leave(); -} - -// Coming from the CPU -void DSPCore_CheckExternalInterrupt() -{ - if (! dsp_SR_is_flag_set(SR_EXT_INT_ENABLE)) - return; - - // Signal the SPU about new mail - DSPCore_SetException(EXP_INT); - - g_dsp.cr &= ~CR_EXTERNAL_INT; -} - - -void DSPCore_CheckExceptions() -{ - // Early out to skip the loop in the common case. - if (g_dsp.exceptions == 0) - return; - - for (int i = 7; i > 0; i--) { - // Seems exp int are not masked by sr_int_enable - if (g_dsp.exceptions & (1 << i)) { - if (dsp_SR_is_flag_set(SR_INT_ENABLE) || (i == EXP_INT)) { - - // store pc and sr until RTI - dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc); - dsp_reg_store_stack(DSP_STACK_D, g_dsp.r.sr); - - g_dsp.pc = i * 2; - g_dsp.exceptions &= ~(1 << i); - if (i == 7) - g_dsp.r.sr &= ~SR_EXT_INT_ENABLE; - else - g_dsp.r.sr &= ~SR_INT_ENABLE; - break; - } else { -#if defined(_DEBUG) || defined(DEBUGFAST) - ERROR_LOG(DSPLLE, "Firing exception %d failed", i); -#endif - } - } - } -} - -// Delegate to JIT or interpreter as appropriate. -// Handle state changes and stepping. -int DSPCore_RunCycles(int cycles) -{ - if (dspjit) - { - cyclesLeft = cycles; - CompiledCode pExecAddr = (CompiledCode)dspjit->enterDispatcher; - pExecAddr(); - - if (g_dsp.external_interrupt_waiting) - { - DSPCore_CheckExternalInterrupt(); - DSPCore_CheckExceptions(); - DSPCore_SetExternalInterrupt(false); - } - - return cyclesLeft; - } - - while (cycles > 0) - { - reswitch: - switch (core_state) - { - case DSPCORE_RUNNING: - // Seems to slow things down -#if defined(_DEBUG) || defined(DEBUGFAST) - 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; - case DSPCORE_STOP: - 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(); -} - -void CompileCurrent() -{ - dspjit->Compile(g_dsp.pc); - - bool retry = true; - - while (retry) - { - retry = false; - for(u16 i = 0x0000; i < 0xffff; ++i) - { - if (!dspjit->unresolvedJumps[i].empty()) - { - u16 addrToCompile = dspjit->unresolvedJumps[i].front(); - dspjit->Compile(addrToCompile); - if (!dspjit->unresolvedJumps[i].empty()) - retry = true; - } - } - } -} - -u16 DSPCore_ReadRegister(int reg) { - switch(reg) { - case DSP_REG_AR0: - case DSP_REG_AR1: - case DSP_REG_AR2: - case DSP_REG_AR3: - return g_dsp.r.ar[reg - DSP_REG_AR0]; - case DSP_REG_IX0: - case DSP_REG_IX1: - case DSP_REG_IX2: - case DSP_REG_IX3: - return g_dsp.r.ix[reg - DSP_REG_IX0]; - case DSP_REG_WR0: - case DSP_REG_WR1: - case DSP_REG_WR2: - case DSP_REG_WR3: - return g_dsp.r.wr[reg - DSP_REG_WR0]; - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - return g_dsp.r.st[reg - DSP_REG_ST0]; - case DSP_REG_ACH0: - case DSP_REG_ACH1: - return g_dsp.r.ac[reg - DSP_REG_ACH0].h; - case DSP_REG_CR: return g_dsp.r.cr; - case DSP_REG_SR: return g_dsp.r.sr; - case DSP_REG_PRODL: return g_dsp.r.prod.l; - case DSP_REG_PRODM: return g_dsp.r.prod.m; - case DSP_REG_PRODH: return g_dsp.r.prod.h; - case DSP_REG_PRODM2: return g_dsp.r.prod.m2; - case DSP_REG_AXL0: - case DSP_REG_AXL1: - return g_dsp.r.ax[reg - DSP_REG_AXL0].l; - case DSP_REG_AXH0: - case DSP_REG_AXH1: - return g_dsp.r.ax[reg - DSP_REG_AXH0].h; - case DSP_REG_ACL0: - case DSP_REG_ACL1: - return g_dsp.r.ac[reg - DSP_REG_ACL0].l; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - return g_dsp.r.ac[reg - DSP_REG_ACM0].m; - default: - _assert_msg_(DSP_CORE, 0, "cannot happen"); - return 0; - } -} - -void DSPCore_WriteRegister(int reg, u16 val) { - switch(reg) { - case DSP_REG_AR0: - case DSP_REG_AR1: - case DSP_REG_AR2: - case DSP_REG_AR3: - g_dsp.r.ar[reg - DSP_REG_AR0] = val; - break; - case DSP_REG_IX0: - case DSP_REG_IX1: - case DSP_REG_IX2: - case DSP_REG_IX3: - g_dsp.r.ix[reg - DSP_REG_IX0] = val; - break; - case DSP_REG_WR0: - case DSP_REG_WR1: - case DSP_REG_WR2: - case DSP_REG_WR3: - g_dsp.r.wr[reg - DSP_REG_WR0] = val; - break; - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - g_dsp.r.st[reg - DSP_REG_ST0] = val; - break; - case DSP_REG_ACH0: - case DSP_REG_ACH1: - g_dsp.r.ac[reg - DSP_REG_ACH0].h = val; - break; - case DSP_REG_CR: g_dsp.r.cr = val; break; - case DSP_REG_SR: g_dsp.r.sr = val; break; - case DSP_REG_PRODL: g_dsp.r.prod.l = val; break; - case DSP_REG_PRODM: g_dsp.r.prod.m = val; break; - case DSP_REG_PRODH: g_dsp.r.prod.h = val; break; - case DSP_REG_PRODM2: g_dsp.r.prod.m2 = val; break; - case DSP_REG_AXL0: - case DSP_REG_AXL1: - g_dsp.r.ax[reg - DSP_REG_AXL0].l = val; - break; - case DSP_REG_AXH0: - case DSP_REG_AXH1: - g_dsp.r.ax[reg - DSP_REG_AXH0].h = val; - break; - case DSP_REG_ACL0: - case DSP_REG_ACL1: - g_dsp.r.ac[reg - DSP_REG_ACL0].l = val; - break; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - g_dsp.r.ac[reg - DSP_REG_ACM0].m = val; - break; - } -} diff --git a/Source/Core/DSPCore/Src/DSPCore.h b/Source/Core/DSPCore/Src/DSPCore.h deleted file mode 100644 index 2f69eb6ee6..0000000000 --- a/Source/Core/DSPCore/Src/DSPCore.h +++ /dev/null @@ -1,306 +0,0 @@ -/*==================================================================== - - 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 "Thread.h" - -#include "DSPBreakpoints.h" -#include "DSPEmitter.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 0x1000 -#define DSP_COEF_SIZE 0x800 -#define DSP_COEF_MASK 0x7ff - -#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_DSCR 0xc9 // DSP DMA Control Reg -#define DSP_DSPA 0xcd // DSP DMA Address (DSP) -#define DSP_DSBL 0xcb // DSP DMA Block Length -#define DSP_DSMAH 0xce // DSP DMA Address High (External) -#define DSP_DSMAL 0xcf // DSP DMA Address Low (External) - -#define DSP_FORMAT 0xd1 // Sample format -#define DSP_ACUNK 0xd2 // Set to 3 on my dumps -#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes -#define DSP_ACSAH 0xd4 // Start of loop -#define DSP_ACSAL 0xd5 -#define DSP_ACEAH 0xd6 // End of sample (and loop) -#define DSP_ACEAL 0xd7 -#define DSP_ACCAH 0xd8 // Current playback position -#define DSP_ACCAL 0xd9 -#define DSP_PRED_SCALE 0xda // ADPCM predictor and scale -#define DSP_YN1 0xdb -#define DSP_YN2 0xdc -#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX. -#define DSP_GAIN 0xde -#define DSP_ACUNK2 0xdf // Set to 0xc on my dumps - -#define DSP_AMDM 0xef // ARAM DMA Request Mask 0: DMA with ARAM unmasked 1: masked - -#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_EXTERNAL_INT 0x0002 -#define CR_HALT 0x0004 -#define CR_INIT 0x0400 - - -// SR bits -#define SR_CARRY 0x0001 -#define SR_OVERFLOW 0x0002 -#define SR_ARITH_ZERO 0x0004 -#define SR_SIGN 0x0008 -#define SR_OVER_S32 0x0010 // set when there there was mod/tst/cmp on accu and result is over s32 -#define SR_TOP2BITS 0x0020 // if the upper (ac?.m/ax?.h) 2 bits are equal -#define SR_LOGIC_ZERO 0x0040 -#define SR_OVERFLOW_STICKY 0x0080 // set at the same time as 0x2 (under same conditions) - but not cleared the same -#define SR_100 0x0100 // unknown -#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so. -#define SR_400 0x0400 // unknown -#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts -#define SR_1000 0x1000 // unknown -#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_STOVF 1 // 0x0002 stack under/over flow -#define EXP_2 2 // 0x0004 -#define EXP_3 3 // 0x0006 -#define EXP_4 4 // 0x0008 -#define EXP_ACCOV 5 // 0x000a accelerator address overflow -#define EXP_6 6 // 0x000c -#define EXP_INT 7 // 0x000e external int (message from cpu) - -typedef struct { - u16 ar[4]; - u16 ix[4]; - u16 wr[4]; - u16 st[4]; - u16 cr; - u16 sr; - union { - u64 val; - struct { - u16 l; - u16 m; - u16 h; - u16 m2;//if this gets in the way, drop it. - }; - } prod; - union { - u32 val; - struct { - u16 l; - u16 h; - }; - } ax[2]; - union { - u64 val; - struct { - u16 l; - u16 m; - u16 h; - }; - } ac[2]; -} DSP_Regs; - -// All the state of the DSP should be in this struct. Any DSP state that is not filled on init -// should be moved here. -struct SDSP -{ - DSP_Regs r; - u16 pc; -#if PROFILE - u16 err_pc; -#endif - - // This is NOT the same cr as r.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 external_interrupt_waiting; - - // DSP hardware stacks. They're mapped to a bunch of registers, such that writes - // to them push and reads pop. - // Let's make stack depth 32 for now, which is way more than what's needed. - // 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; - - // Mailbox. - volatile u16 mbox[2][2]; - - // Mutex protecting the mailbox. - Common::CriticalSection g_CriticalSection; - - // Accelerator / DMA / other hardware registers. Not GPRs. - u16 ifx_regs[256]; - - // 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; -extern DSPEmitter *dspjit; -extern u16 cyclesLeft; - -bool DSPCore_Init(const char *irom_filename, const char *coef_filename, - bool bUsingJIT); - -void DSPCore_Reset(); -void DSPCore_Shutdown(); // Frees all allocated memory. - -void DSPCore_CheckExternalInterrupt(); -void DSPCore_CheckExceptions(); -void DSPCore_SetExternalInterrupt(bool val); - -// sets a flag in the pending exception register. -void DSPCore_SetException(u8 level); - -void CompileCurrent(); - -enum DSPCoreState -{ - DSPCORE_STOP = 0, - DSPCORE_RUNNING, - DSPCORE_STEPPING, -}; - -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(); - -u16 DSPCore_ReadRegister(int reg); -void DSPCore_WriteRegister(int reg, u16 val); - -#endif // _DSPCORE_H diff --git a/Source/Core/DSPCore/Src/DSPEmitter.cpp b/Source/Core/DSPCore/Src/DSPEmitter.cpp deleted file mode 100644 index e68fea7e18..0000000000 --- a/Source/Core/DSPCore/Src/DSPEmitter.cpp +++ /dev/null @@ -1,446 +0,0 @@ -// Copyright (C) 2010 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 <cstring> - -#include "DSPEmitter.h" -#include "DSPMemoryMap.h" -#include "DSPCore.h" -#include "DSPInterpreter.h" -#include "DSPAnalyzer.h" -#include "Jit/DSPJitUtil.h" -#include "x64Emitter.h" -#include "ABI.h" - -#define MAX_BLOCK_SIZE 250 -#define DSP_IDLE_SKIP_CYCLES 0x1000 - -using namespace Gen; - -DSPEmitter::DSPEmitter() : gpr(*this), storeIndex(-1), storeIndex2(-1) -{ - m_compiledCode = NULL; - - AllocCodeSpace(COMPILED_CODE_SIZE); - - blocks = new CompiledCode[MAX_BLOCKS]; - blockLinks = new Block[MAX_BLOCKS]; - blockSize = new u16[MAX_BLOCKS]; - unresolvedJumps = new std::list<u16>[MAX_BLOCKS]; - - compileSR = 0; - compileSR |= SR_INT_ENABLE; - compileSR |= SR_EXT_INT_ENABLE; - - CompileDispatcher(); - stubEntryPoint = CompileStub(); - - //clear all of the block references - for(int i = 0x0000; i < MAX_BLOCKS; i++) - { - blocks[i] = (CompiledCode)stubEntryPoint; - blockLinks[i] = 0; - blockSize[i] = 0; - } -} - -DSPEmitter::~DSPEmitter() -{ - delete[] blocks; - delete[] blockLinks; - delete[] blockSize; - FreeCodeSpace(); -} - -void DSPEmitter::ClearIRAM() { - // ClearCodeSpace(); - for(int i = 0x0000; i < 0x1000; i++) - { - blocks[i] = (CompiledCode)stubEntryPoint; - blockLinks[i] = 0; - blockSize[i] = 0; - } -} - -// Must go out of block if exception is detected -void DSPEmitter::checkExceptions(u32 retval) -{ - // Check for interrupts and exceptions -#ifdef _M_IX86 // All32 - TEST(8, M(&g_dsp.exceptions), Imm8(0xff)); -#else - MOV(64, R(RAX), ImmPtr(&g_dsp.exceptions)); - TEST(8, MatR(RAX), Imm8(0xff)); -#endif - FixupBranch skipCheck = J_CC(CC_Z); - -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC)); -#endif - - DSPJitRegCache c(gpr); - SaveDSPRegs(); - ABI_CallFunction((void *)&DSPCore_CheckExceptions); - MOV(32, R(EAX), Imm32(retval)); - JMP(returnDispatcher, true); - gpr.flushRegs(c,false); - - SetJumpTarget(skipCheck); -} - -void DSPEmitter::Default(UDSPInstruction inst) -{ - if (opTable[inst]->reads_pc) - { - // Increment PC - we shouldn't need to do this for every instruction. only for branches and end of block. - // Fallbacks to interpreter need this for fetching immediate values - -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 1)); -#endif - } - - // Fall back to interpreter - SaveDSPRegs(); - ABI_CallFunctionC16((void*)opTable[inst]->intFunc, inst); - LoadDSPRegs(); -} - -void DSPEmitter::EmitInstruction(UDSPInstruction inst) -{ - const DSPOPCTemplate *tinst = GetOpTemplate(inst); - bool ext_is_jit = false; - - // Call extended - if (tinst->extended) { - if ((inst >> 12) == 0x3) { - if (! extOpTable[inst & 0x7F]->jitFunc) { - // Fall back to interpreter - SaveDSPRegs(); - ABI_CallFunctionC16((void*)extOpTable[inst & 0x7F]->intFunc, inst); - LoadDSPRegs(); - INFO_LOG(DSPLLE, "Instruction not JITed(ext part): %04x\n", inst); - ext_is_jit = false; - } else { - (this->*extOpTable[inst & 0x7F]->jitFunc)(inst); - ext_is_jit = true; - } - } else { - if (!extOpTable[inst & 0xFF]->jitFunc) { - // Fall back to interpreter - SaveDSPRegs(); - ABI_CallFunctionC16((void*)extOpTable[inst & 0xFF]->intFunc, inst); - LoadDSPRegs(); - INFO_LOG(DSPLLE, "Instruction not JITed(ext part): %04x\n", inst); - ext_is_jit = false; - } else { - (this->*extOpTable[inst & 0xFF]->jitFunc)(inst); - ext_is_jit = true; - } - } - } - - // Main instruction - if (!opTable[inst]->jitFunc) { - Default(inst); - INFO_LOG(DSPLLE, "Instruction not JITed(main part): %04x\n", inst); - } - else - { - (this->*opTable[inst]->jitFunc)(inst); - } - - // Backlog - if (tinst->extended) { - if (!ext_is_jit) { - //need to call the online cleanup function because - //the writeBackLog gets populated at runtime - SaveDSPRegs(); - ABI_CallFunction((void*)::applyWriteBackLog); - LoadDSPRegs(); - } else { - popExtValueToReg(); - } - } -} - -void DSPEmitter::unknown_instruction(UDSPInstruction inst) -{ - PanicAlert("unknown_instruction %04x - Fix me ;)", inst); -} - -void DSPEmitter::Compile(u16 start_addr) -{ - // Remember the current block address for later - startAddr = start_addr; - unresolvedJumps[start_addr].clear(); - - const u8 *entryPoint = AlignCode16(); - - /* - // Check for other exceptions - if (dsp_SR_is_flag_set(SR_INT_ENABLE)) - return; - - if (g_dsp.exceptions == 0) - return; - */ - - LoadDSPRegs(); - - blockLinkEntry = GetCodePtr(); - - compilePC = start_addr; - bool fixup_pc = false; - blockSize[start_addr] = 0; - - while (compilePC < start_addr + MAX_BLOCK_SIZE) - { - if (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_CHECK_INT) - checkExceptions(blockSize[start_addr]); - - UDSPInstruction inst = dsp_imem_read(compilePC); - const DSPOPCTemplate *opcode = GetOpTemplate(inst); - - EmitInstruction(inst); - - blockSize[start_addr]++; - compilePC += opcode->size; - - // If the block was trying to link into itself, remove the link - unresolvedJumps[start_addr].remove(compilePC); - - fixup_pc = true; - - // Handle loop condition, only if current instruction was flagged as a loop destination - // by the analyzer. - if (DSPAnalyzer::code_flags[compilePC-1] & DSPAnalyzer::CODE_LOOP_END) - { -#ifdef _M_IX86 // All32 - MOVZX(32, 16, EAX, M(&(g_dsp.r.st[2]))); -#else - MOV(64, R(R11), ImmPtr(&g_dsp.r)); - MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[2]))); -#endif - CMP(32, R(EAX), Imm32(0)); - FixupBranch rLoopAddressExit = J_CC(CC_LE, true); - -#ifdef _M_IX86 // All32 - MOVZX(32, 16, EAX, M(&g_dsp.r.st[3])); -#else - MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[3]))); -#endif - CMP(32, R(EAX), Imm32(0)); - FixupBranch rLoopCounterExit = J_CC(CC_LE, true); - - if (!opcode->branch) - { - //branch insns update the g_dsp.pc -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC)); -#endif - } - - // These functions branch and therefore only need to be called in the - // end of each block and in this order - DSPJitRegCache c(gpr); - HandleLoop(); - SaveDSPRegs(); - if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP) - { - MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES)); - } - else - { - MOV(16, R(EAX), Imm16(blockSize[start_addr])); - } - JMP(returnDispatcher, true); - gpr.flushRegs(c,false); - - SetJumpTarget(rLoopAddressExit); - SetJumpTarget(rLoopCounterExit); - } - - if (opcode->branch) - { - //don't update g_dsp.pc -- the branch insn already did - fixup_pc = false; - if (opcode->uncond_branch) - { - break; - } - else if (!opcode->jitFunc) - { - //look at g_dsp.pc if we actually branched -#ifdef _M_IX86 // All32 - MOV(16, R(AX), M(&g_dsp.pc)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, R(AX), MatR(RAX)); -#endif - CMP(16, R(AX), Imm16(compilePC)); - FixupBranch rNoBranch = J_CC(CC_Z); - - DSPJitRegCache c(gpr); - //don't update g_dsp.pc -- the branch insn already did - SaveDSPRegs(); - if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP) - { - MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES)); - } - else - { - MOV(16, R(EAX), Imm16(blockSize[start_addr])); - } - JMP(returnDispatcher, true); - gpr.flushRegs(c,false); - - SetJumpTarget(rNoBranch); - } - } - - // End the block if we're before an idle skip address - if (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_IDLE_SKIP) - { - break; - } - } - - if (fixup_pc) { -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC)); -#endif - } - - blocks[start_addr] = (CompiledCode)entryPoint; - - // Mark this block as a linkable destination if it does not contain - // any unresolved CALL's - if (unresolvedJumps[start_addr].empty()) - { - blockLinks[start_addr] = blockLinkEntry; - - for(u16 i = 0x0000; i < 0xffff; ++i) - { - if (!unresolvedJumps[i].empty()) - { - // Check if there were any blocks waiting for this block to be linkable - unsigned int size = unresolvedJumps[i].size(); - unresolvedJumps[i].remove(start_addr); - if (unresolvedJumps[i].size() < size) - { - // Mark the block to be recompiled again - blocks[i] = (CompiledCode)stubEntryPoint; - blockLinks[i] = 0; - blockSize[i] = 0; - } - } - } - } - - if (blockSize[start_addr] == 0) - { - // just a safeguard, should never happen anymore. - // if it does we might get stuck over in RunForCycles. - ERROR_LOG(DSPLLE, "Block at 0x%04x has zero size", start_addr); - blockSize[start_addr] = 1; - } - - SaveDSPRegs(); - if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP) - { - MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES)); - } - else - { - MOV(16, R(EAX), Imm16(blockSize[start_addr])); - } - JMP(returnDispatcher, true); -} - -const u8 *DSPEmitter::CompileStub() -{ - const u8 *entryPoint = AlignCode16(); - ABI_CallFunction((void *)&CompileCurrent); - //MOVZX(32, 16, ECX, M(&g_dsp.pc)); - XOR(32, R(EAX), R(EAX)); // Return 0 cycles executed - JMP(returnDispatcher); - return entryPoint; -} - -void DSPEmitter::CompileDispatcher() -{ - enterDispatcher = AlignCode16(); - ABI_PushAllCalleeSavedRegsAndAdjustStack(); - - const u8 *dispatcherLoop = GetCodePtr(); - - // Check for DSP halt -#ifdef _M_IX86 - TEST(8, M(&g_dsp.cr), Imm8(CR_HALT)); -#else - MOV(64, R(RAX), ImmPtr(&g_dsp.cr)); - TEST(8, MatR(RAX), Imm8(CR_HALT)); -#endif - FixupBranch _halt = J_CC(CC_NE); - -#ifdef _M_IX86 - MOVZX(32, 16, ECX, M(&g_dsp.pc)); -#else - MOV(64, R(RCX), ImmPtr(&g_dsp.pc)); - MOVZX(64, 16, RCX, MatR(RCX)); -#endif - - // Execute block. Cycles executed returned in EAX. -#ifdef _M_IX86 - MOV(32, R(EBX), ImmPtr(blocks)); - JMPptr(MComplex(EBX, ECX, SCALE_4, 0)); -#else - MOV(64, R(RBX), ImmPtr(blocks)); - JMPptr(MComplex(RBX, RCX, SCALE_8, 0)); -#endif - - returnDispatcher = GetCodePtr(); - - // Decrement cyclesLeft -#ifdef _M_IX86 - SUB(16, M(&cyclesLeft), R(EAX)); -#else - MOV(64, R(R12), ImmPtr(&cyclesLeft)); - SUB(16, MatR(R12), R(EAX)); -#endif - - J_CC(CC_A, dispatcherLoop); - - // DSP gave up the remaining cycles. - SetJumpTarget(_halt); - //MOV(32, M(&cyclesLeft), Imm32(0)); - ABI_PopAllCalleeSavedRegsAndAdjustStack(); - RET(); -} diff --git a/Source/Core/DSPCore/Src/DSPEmitter.h b/Source/Core/DSPCore/Src/DSPEmitter.h deleted file mode 100644 index 17f1850001..0000000000 --- a/Source/Core/DSPCore/Src/DSPEmitter.h +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (C) 2003 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 _DSPEMITTER_H -#define _DSPEMITTER_H - -#include <list> - -#include "DSPCommon.h" -#include "x64Emitter.h" -#include "Jit/DSPJitRegCache.h" - -#define COMPILED_CODE_SIZE sizeof(void *) * 0x200000 - -#define MAX_BLOCKS 0x10000 - -typedef u32 (*CompiledCode)(); -typedef const u8 *Block; - -class DSPEmitter : public Gen::XCodeBlock, NonCopyable -{ -public: - DSPEmitter(); - ~DSPEmitter(); - - Block m_compiledCode; - - void EmitInstruction(UDSPInstruction inst); - void unknown_instruction(UDSPInstruction inst); - void ClearIRAM(); - - void CompileDispatcher(); - Block CompileStub(); - void Compile(u16 start_addr); - void ClearCallFlag(); - - void Default(UDSPInstruction inst); - - // CC Util - void Update_SR_Register64(Gen::X64Reg val = Gen::EAX); - void Update_SR_Register64_Carry(Gen::X64Reg val = Gen::EAX); - void Update_SR_Register64_Carry2(Gen::X64Reg val = Gen::EAX); - void Update_SR_Register16(Gen::X64Reg val = Gen::EAX); - void Update_SR_Register16_OverS32(Gen::X64Reg val = Gen::EAX); - - // Register helpers - void setCompileSR(u16 bit); - void clrCompileSR(u16 bit); - void checkExceptions(u32 retval); - - // Memory helper functions - void increment_addr_reg(int reg); - void decrement_addr_reg(int reg); - void increase_addr_reg(int reg); - void decrease_addr_reg(int reg); - void imem_read(); - void dmem_read(); - void dmem_read_imm(u16 addr); - void dmem_write(); - void dmem_write_imm(u16 addr); - - // Ext command helpers - void pushExtValueFromReg(u16 dreg, u16 sreg); - void popExtValueToReg(); - void pushExtValueFromMem(u16 dreg, u16 sreg); - void pushExtValueFromMem2(u16 dreg, u16 sreg); - void zeroWriteBackLog(const UDSPInstruction opc); - - // Ext commands - void l(const UDSPInstruction opc); - void ln(const UDSPInstruction opc); - void ls(const UDSPInstruction opc); - void lsn(const UDSPInstruction opc); - void lsm(const UDSPInstruction opc); - void lsnm(const UDSPInstruction opc); - void sl(const UDSPInstruction opc); - void sln(const UDSPInstruction opc); - void slm(const UDSPInstruction opc); - void slnm(const UDSPInstruction opc); - void s(const UDSPInstruction opc); - void sn(const UDSPInstruction opc); - void ld(const UDSPInstruction opc); - void ldn(const UDSPInstruction opc); - void ldm(const UDSPInstruction opc); - void ldnm(const UDSPInstruction opc); - void mv(const UDSPInstruction opc); - void dr(const UDSPInstruction opc); - void ir(const UDSPInstruction opc); - void nr(const UDSPInstruction opc); - void nop(const UDSPInstruction opc) {} - - // Command helpers - void dsp_reg_stack_push(int stack_reg); - void dsp_reg_stack_pop(int stack_reg); - void dsp_reg_store_stack(int stack_reg, Gen::X64Reg host_sreg = Gen::EDX); - void dsp_reg_load_stack(int stack_reg, Gen::X64Reg host_dreg = Gen::EDX); - void dsp_reg_store_stack_imm(int stack_reg, u16 val); - void dsp_op_write_reg(int reg, Gen::X64Reg host_sreg); - void dsp_op_write_reg_imm(int reg, u16 val); - void dsp_conditional_extend_accum(int reg); - void dsp_conditional_extend_accum_imm(int reg, u16 val); - void dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend = NONE); - - // Commands - void dar(const UDSPInstruction opc); - void iar(const UDSPInstruction opc); - void subarn(const UDSPInstruction opc); - void addarn(const UDSPInstruction opc); - void sbclr(const UDSPInstruction opc); - void sbset(const UDSPInstruction opc); - void srbith(const UDSPInstruction opc); - void lri(const UDSPInstruction opc); - void lris(const UDSPInstruction opc); - void mrr(const UDSPInstruction opc); - void nx(const UDSPInstruction opc); - - // Branch - void HandleLoop(); - void jcc(const UDSPInstruction opc); - void jmprcc(const UDSPInstruction opc); - void call(const UDSPInstruction opc); - void callr(const UDSPInstruction opc); - void ifcc(const UDSPInstruction opc); - void ret(const UDSPInstruction opc); - void rti(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); - - // Load/Store - void srs(const UDSPInstruction opc); - void lrs(const UDSPInstruction opc); - void lr(const UDSPInstruction opc); - void sr(const UDSPInstruction opc); - void si(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 ilrr(const UDSPInstruction opc); - void ilrrd(const UDSPInstruction opc); - void ilrri(const UDSPInstruction opc); - void ilrrn(const UDSPInstruction opc); - - // Arithmetic - void clr(const UDSPInstruction opc); - void clrl(const UDSPInstruction opc); - void andcf(const UDSPInstruction opc); - void andf(const UDSPInstruction opc); - void tst(const UDSPInstruction opc); - void tstaxh(const UDSPInstruction opc); - void cmp(const UDSPInstruction opc); - void cmpar(const UDSPInstruction opc); - void cmpi(const UDSPInstruction opc); - void cmpis(const UDSPInstruction opc); - void xorr(const UDSPInstruction opc); - void andr(const UDSPInstruction opc); - void orr(const UDSPInstruction opc); - void andc(const UDSPInstruction opc); - void orc(const UDSPInstruction opc); - void xorc(const UDSPInstruction opc); - void notc(const UDSPInstruction opc); - void xori(const UDSPInstruction opc); - void andi(const UDSPInstruction opc); - void ori(const UDSPInstruction opc); - void addr(const UDSPInstruction opc); - void addax(const UDSPInstruction opc); - void add(const UDSPInstruction opc); - void addp(const UDSPInstruction opc); - void addaxl(const UDSPInstruction opc); - void addi(const UDSPInstruction opc); - void addis(const UDSPInstruction opc); - void incm(const UDSPInstruction opc); - void inc(const UDSPInstruction opc); - void subr(const UDSPInstruction opc); - void subax(const UDSPInstruction opc); - void sub(const UDSPInstruction opc); - void subp(const UDSPInstruction opc); - void decm(const UDSPInstruction opc); - void dec(const UDSPInstruction opc); - void neg(const UDSPInstruction opc); - void abs(const UDSPInstruction opc); - void movr(const UDSPInstruction opc); - void movax(const UDSPInstruction opc); - void mov(const UDSPInstruction opc); - void lsl16(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 lsrnrx(const UDSPInstruction opc); - void asrnrx(const UDSPInstruction opc); - void lsrnr(const UDSPInstruction opc); - void asrnr(const UDSPInstruction opc); - - // Multipliers - void multiply(); - void multiply_add(); - void multiply_sub(); - void multiply_mulx(u8 axh0, u8 axh1); - void clrp(const UDSPInstruction opc); - void tstprod(const UDSPInstruction opc); - void movp(const UDSPInstruction opc); - void movnp(const UDSPInstruction opc); - void movpz(const UDSPInstruction opc); - void addpaxz(const UDSPInstruction opc); - void mulaxh(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 mulc(const UDSPInstruction opc); - void mulcac(const UDSPInstruction opc); - void mulcmv(const UDSPInstruction opc); - void mulcmvz(const UDSPInstruction opc); - void maddx(const UDSPInstruction opc); - void msubx(const UDSPInstruction opc); - void maddc(const UDSPInstruction opc); - void msubc(const UDSPInstruction opc); - void madd(const UDSPInstruction opc); - void msub(const UDSPInstruction opc); - - // CALL this to start the dispatcher - const u8 *enterDispatcher; - const u8 *stubEntryPoint; - const u8 *returnDispatcher; - u16 compilePC; - u16 startAddr; - Block *blockLinks; - u16 *blockSize; - std::list<u16> *unresolvedJumps; - - DSPJitRegCache gpr; - - void LoadDSPRegs(); - void SaveDSPRegs(); - -private: - CompiledCode *blocks; - Block blockLinkEntry; - u16 compileSR; - - // The index of the last stored ext value (compile time). - int storeIndex; - int storeIndex2; - - // Counts down. - // int cycles; - - - void Update_SR_Register(Gen::X64Reg val = Gen::EAX); - - void ToMask(Gen::X64Reg value_reg = Gen::EDI); - void dsp_increment_one(Gen::X64Reg ar = Gen::EAX, Gen::X64Reg wr = Gen::EDX, Gen::X64Reg wr_pow = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI); - void dsp_decrement_one(Gen::X64Reg ar = Gen::EAX, Gen::X64Reg wr = Gen::EDX, Gen::X64Reg wr_pow = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI); - void get_long_prod(Gen::X64Reg long_prod = Gen::RAX); - void get_long_prod_round_prodl(Gen::X64Reg long_prod = Gen::RAX); - void set_long_prod(); - void round_long_acc(Gen::X64Reg long_acc = Gen::EAX); - void set_long_acc(int _reg, Gen::X64Reg acc = Gen::EAX); - void get_acc_h(int _reg, Gen::X64Reg acc = Gen::EAX, bool sign = true); - void set_acc_h(int _reg, Gen::OpArg arg = R(Gen::EAX)); - void get_acc_m(int _reg, Gen::X64Reg acc = Gen::EAX, bool sign = true); - void set_acc_m(int _reg, Gen::OpArg arg = R(Gen::EAX)); - void get_acc_l(int _reg, Gen::X64Reg acc = Gen::EAX, bool sign = true); - void set_acc_l(int _reg, Gen::OpArg arg = R(Gen::EAX)); - void get_long_acx(int _reg, Gen::X64Reg acx = Gen::EAX); - void get_ax_l(int _reg, Gen::X64Reg acx = Gen::EAX); - void get_ax_h(int _reg, Gen::X64Reg acc = Gen::EAX); - void get_long_acc(int _reg, Gen::X64Reg acc = Gen::EAX); -}; - - -#endif // _DSPEMITTER_H - diff --git a/Source/Core/DSPCore/Src/DSPHWInterface.cpp b/Source/Core/DSPCore/Src/DSPHWInterface.cpp deleted file mode 100644 index a2862affe3..0000000000 --- a/Source/Core/DSPCore/Src/DSPHWInterface.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/*==================================================================== - - filename: gdsp_interface.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. - - ====================================================================*/ - -#include "Thread.h" -#include "MemoryUtil.h" - -#include "DSPCore.h" -#include "DSPHost.h" -#include "DSPTables.h" -#include "DSPAnalyzer.h" -#include "DSPAccelerator.h" -#include "DSPInterpreter.h" -#include "DSPHWInterface.h" -#include "CPUDetect.h" - -#if _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__) -#include <tmmintrin.h> -#endif - -void gdsp_do_dma(); - -Common::CriticalSection g_CriticalSection; - -void gdsp_ifx_init() -{ - for (int i = 0; i < 256; i++) - { - g_dsp.ifx_regs[i] = 0; - } - - g_dsp.mbox[0][0] = 0; - g_dsp.mbox[0][1] = 0; - g_dsp.mbox[1][0] = 0; - g_dsp.mbox[1][1] = 0; -} - - -u32 gdsp_mbox_peek(u8 mbx) -{ - if (DSPHost_OnThread()) - g_CriticalSection.Enter(); - u32 value = ((g_dsp.mbox[mbx][0] << 16) | g_dsp.mbox[mbx][1]); - if (DSPHost_OnThread()) - g_CriticalSection.Leave(); - return value; -} - -void gdsp_mbox_write_h(u8 mbx, u16 val) -{ - if (DSPHost_OnThread()) - g_CriticalSection.Enter(); - g_dsp.mbox[mbx][0] = val & 0x7fff; - if (DSPHost_OnThread()) - g_CriticalSection.Leave(); -} - - -void gdsp_mbox_write_l(u8 mbx, u16 val) -{ - if (DSPHost_OnThread()) - g_CriticalSection.Enter(); - g_dsp.mbox[mbx][1] = val; - g_dsp.mbox[mbx][0] |= 0x8000; - if (DSPHost_OnThread()) - g_CriticalSection.Leave(); - -#if defined(_DEBUG) || defined(DEBUGFAST) - if (mbx == GDSP_MBOX_DSP) - { - NOTICE_LOG(DSP_MAIL, "DSP(WM) B:%i M:0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.pc); - } else { - NOTICE_LOG(DSP_MAIL, "CPU(WM) B:%i M:0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_CPU), g_dsp.pc); - } -#endif -} - - -u16 gdsp_mbox_read_h(u8 mbx) -{ - return g_dsp.mbox[mbx][0]; // TODO: mask away the top bit? -} - - -u16 gdsp_mbox_read_l(u8 mbx) -{ - if (DSPHost_OnThread()) - g_CriticalSection.Enter(); - - u16 val = g_dsp.mbox[mbx][1]; - g_dsp.mbox[mbx][0] &= ~0x8000; - - - if (DSPHost_OnThread()) - g_CriticalSection.Leave(); - -#if defined(_DEBUG) || defined(DEBUGFAST) - if (mbx == GDSP_MBOX_DSP) - { - NOTICE_LOG(DSP_MAIL, "DSP(RM) B:%i M:0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.pc); - } else { - NOTICE_LOG(DSP_MAIL, "CPU(RM) B:%i M:0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_CPU), g_dsp.pc); - } -#endif - - return val; -} - - -void gdsp_ifx_write(u32 addr, u32 val) -{ - switch (addr & 0xff) - { - case DSP_DIRQ: - if (val & 0x1) - DSPHost_InterruptRequest(); - else - INFO_LOG(DSPLLE, "Unknown Interrupt Request pc=%04x (%04x)", g_dsp.pc, val); - break; - - case DSP_DMBH: - gdsp_mbox_write_h(GDSP_MBOX_DSP, val); - break; - - case DSP_DMBL: - gdsp_mbox_write_l(GDSP_MBOX_DSP, val); - break; - - case DSP_CMBH: - return gdsp_mbox_write_h(GDSP_MBOX_CPU, val); - - case DSP_CMBL: - return gdsp_mbox_write_l(GDSP_MBOX_CPU, val); - - case DSP_DSBL: - g_dsp.ifx_regs[DSP_DSBL] = val; - g_dsp.ifx_regs[DSP_DSCR] |= 4; // Doesn't really matter since we do DMA instantly - if (!g_dsp.ifx_regs[DSP_AMDM]) - gdsp_do_dma(); - else - NOTICE_LOG(DSPLLE, "Masked DMA skipped"); - g_dsp.ifx_regs[DSP_DSCR] &= ~4; - g_dsp.ifx_regs[DSP_DSBL] = 0; - break; - - case DSP_ACDATA1: // Accelerator write (Zelda type) - "UnkZelda" - dsp_write_aram_d3(val); - break; - - case DSP_GAIN: - if (val) { - INFO_LOG(DSPLLE,"Gain Written: 0x%04x", val); - } - case DSP_DSPA: - case DSP_DSMAH: - case DSP_DSMAL: - case DSP_DSCR: - g_dsp.ifx_regs[addr & 0xFF] = val; - break; -/* - case DSP_ACCAL: - dsp_step_accelerator(); - break; -*/ - default: - if ((addr & 0xff) >= 0xa0) { - if (pdlabels[(addr & 0xFF) - 0xa0].name && pdlabels[(addr & 0xFF) - 0xa0].description) { - INFO_LOG(DSPLLE, "%04x MW %s (%04x)", g_dsp.pc, pdlabels[(addr & 0xFF) - 0xa0].name, val); - } - else { - ERROR_LOG(DSPLLE, "%04x MW %04x (%04x)", g_dsp.pc, addr, val); - } - } - else { - ERROR_LOG(DSPLLE, "%04x MW %04x (%04x)", g_dsp.pc, addr, val); - } - g_dsp.ifx_regs[addr & 0xFF] = val; - break; - } -} - -u16 gdsp_ifx_read(u16 addr) -{ - switch (addr & 0xff) - { - case DSP_DMBH: - return gdsp_mbox_read_h(GDSP_MBOX_DSP); - - case DSP_DMBL: - return gdsp_mbox_read_l(GDSP_MBOX_DSP); - - case DSP_CMBH: - return gdsp_mbox_read_h(GDSP_MBOX_CPU); - - case DSP_CMBL: - return gdsp_mbox_read_l(GDSP_MBOX_CPU); - - case DSP_DSCR: - return g_dsp.ifx_regs[addr & 0xFF]; - - case DSP_ACCELERATOR: // ADPCM Accelerator reads - return dsp_read_accelerator(); - - case DSP_ACDATA1: // Accelerator reads (Zelda type) - "UnkZelda" - return dsp_read_aram_d3(); - - default: - if ((addr & 0xff) >= 0xa0) { - if (pdlabels[(addr & 0xFF) - 0xa0].name && pdlabels[(addr & 0xFF) - 0xa0].description) { - INFO_LOG(DSPLLE, "%04x MR %s (%04x)", g_dsp.pc, pdlabels[(addr & 0xFF) - 0xa0].name, g_dsp.ifx_regs[addr & 0xFF]); - } - else { - ERROR_LOG(DSPLLE, "%04x MR %04x (%04x)", g_dsp.pc, addr, g_dsp.ifx_regs[addr & 0xFF]); - } - } - else { - ERROR_LOG(DSPLLE, "%04x MR %04x (%04x)", g_dsp.pc, addr, g_dsp.ifx_regs[addr & 0xFF]); - } - return g_dsp.ifx_regs[addr & 0xFF]; - } -} - -void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size) -{ - UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false); - - u8* dst = ((u8*)g_dsp.iram); - for (u32 i = 0; i < size; i += 2) - { - // TODO : this may be different on Wii. - *(u16*)&dst[dsp_addr + i] = Common::swap16(*(const u16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff]); - } - WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false); - - g_dsp.iram_crc = DSPHost_CodeLoaded(g_dsp.cpu_ram + (addr & 0x0fffffff), size); - - NOTICE_LOG(DSPLLE, "*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)", addr, dsp_addr, g_dsp.iram_crc); - - if (dspjit) - dspjit->ClearIRAM(); - - DSPAnalyzer::Analyze(); -} - - -void gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size) -{ - ERROR_LOG(DSPLLE, "*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)", dsp_addr / 2, addr, size); -} - -static const __m128i s_mask = _mm_set_epi32(0x0E0F0C0DL, 0x0A0B0809L, 0x06070405L, 0x02030001L); - -// TODO: These should eat clock cycles. -void gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size) -{ - u8* dst = ((u8*)g_dsp.dram); - -#if _M_SSE >= 0x301 - if (cpu_info.bSSSE3 && !(size % 16)) - { - for (u32 i = 0; i < size; i += 16) - { - _mm_storeu_si128((__m128i *)&dst[dsp_addr + i], _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF]), s_mask)); - } - } - else -#endif - { - for (u32 i = 0; i < size; i += 2) - { - *(u16*)&dst[dsp_addr + i] = Common::swap16(*(const u16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF]); - } - } - INFO_LOG(DSPLLE, "*** ddma_in RAM (0x%08x) -> DRAM_DSP (0x%04x) : size (0x%08x)", addr, dsp_addr / 2, size); -} - - -void gdsp_ddma_out(u16 dsp_addr, u32 addr, u32 size) -{ - const u8* src = ((const u8*)g_dsp.dram); - -#if _M_SSE >= 0x301 - if (cpu_info.bSSSE3 && !(size % 16)) - { - for (u32 i = 0; i < size; i += 16) - { - _mm_storeu_si128((__m128i *)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF], _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)&src[dsp_addr + i]), s_mask)); - } - } - else -#endif - { - for (u32 i = 0; i < size; i += 2) - { - *(u16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF] = Common::swap16(*(const u16*)&src[dsp_addr + i]); - } - } - - INFO_LOG(DSPLLE, "*** ddma_out DRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)", dsp_addr / 2, addr, size); -} - -void gdsp_do_dma() -{ - u16 ctl; - u32 addr; - u16 dsp_addr; - u16 len; - - addr = (g_dsp.ifx_regs[DSP_DSMAH] << 16) | g_dsp.ifx_regs[DSP_DSMAL]; - ctl = g_dsp.ifx_regs[DSP_DSCR]; - dsp_addr = g_dsp.ifx_regs[DSP_DSPA] * 2; - len = g_dsp.ifx_regs[DSP_DSBL]; - - if (len > 0x4000) - { - ERROR_LOG(DSPLLE, "DMA ERROR pc: %04x ctl: %04x addr: %08x da: %04x size: %04x", g_dsp.pc, ctl, addr, dsp_addr, len); - exit(0); - } -#if defined(_DEBUG) || defined(DEBUGFAST) - DEBUG_LOG(DSPLLE, "DMA pc: %04x ctl: %04x addr: %08x da: %04x size: %04x", g_dsp.pc, ctl, addr, dsp_addr, len); -#endif - switch (ctl & 0x3) - { - case (DSP_CR_DMEM | DSP_CR_TO_CPU): - gdsp_ddma_out(dsp_addr, addr, len); - break; - - case (DSP_CR_DMEM | DSP_CR_FROM_CPU): - gdsp_ddma_in(dsp_addr, addr, len); - break; - - case (DSP_CR_IMEM | DSP_CR_TO_CPU): - gdsp_idma_out(dsp_addr, addr, len); - break; - - case (DSP_CR_IMEM | DSP_CR_FROM_CPU): - gdsp_idma_in(dsp_addr, addr, len); - break; - } -} diff --git a/Source/Core/DSPCore/Src/DSPHWInterface.h b/Source/Core/DSPCore/Src/DSPHWInterface.h deleted file mode 100644 index df83f61e4b..0000000000 --- a/Source/Core/DSPCore/Src/DSPHWInterface.h +++ /dev/null @@ -1,47 +0,0 @@ -/*==================================================================== - - filename: gdsp_interface.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 _GDSP_INTERFACE_H -#define _GDSP_INTERFACE_H - -#include "Common.h" - -#define GDSP_MBOX_CPU 0 -#define GDSP_MBOX_DSP 1 - -u32 gdsp_mbox_peek(u8 mbx); -void gdsp_mbox_write_h(u8 mbx, u16 val); -void gdsp_mbox_write_l(u8 mbx, u16 val); -u16 gdsp_mbox_read_h(u8 mbx); -u16 gdsp_mbox_read_l(u8 mbx); - -void gdsp_ifx_init(); - -void gdsp_ifx_write(u32 addr, u32 val); -u16 gdsp_ifx_read(u16 addr); - -void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size); - -#endif diff --git a/Source/Core/DSPCore/Src/DSPHost.h b/Source/Core/DSPCore/Src/DSPHost.h deleted file mode 100644 index b3361f50e1..0000000000 --- a/Source/Core/DSPCore/Src/DSPHost.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2003 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. - -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 diff --git a/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp b/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp deleted file mode 100644 index 644ce60663..0000000000 --- a/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (C) 2003 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, bool carry, bool overflow) -{ - g_dsp.r.sr &= ~SR_CMP_MASK; - - // 0x01 - if (carry) - { - g_dsp.r.sr |= SR_CARRY; - } - - // 0x02 and 0x80 - if (overflow) - { - g_dsp.r.sr |= SR_OVERFLOW; - g_dsp.r.sr |= SR_OVERFLOW_STICKY; - } - - // 0x04 - if (_Value == 0) - { - g_dsp.r.sr |= SR_ARITH_ZERO; - } - - // 0x08 - if (_Value < 0) - { - g_dsp.r.sr |= SR_SIGN; - } - - // 0x10 - if (_Value != (s32)_Value) - { - g_dsp.r.sr |= SR_OVER_S32; - } - - // 0x20 - Checks if top bits of m are equal - if (((_Value & 0xc0000000) == 0) || ((_Value & 0xc0000000) == 0xc0000000)) - { - g_dsp.r.sr |= SR_TOP2BITS; - } -} - - -void Update_SR_Register16(s16 _Value, bool carry, bool overflow, bool overS32) -{ - g_dsp.r.sr &= ~SR_CMP_MASK; - - // 0x01 - if (carry) - { - g_dsp.r.sr |= SR_CARRY; - } - - // 0x02 and 0x80 - if (overflow) - { - g_dsp.r.sr |= SR_OVERFLOW; - g_dsp.r.sr |= SR_OVERFLOW_STICKY; - } - - // 0x04 - if (_Value == 0) - { - g_dsp.r.sr |= SR_ARITH_ZERO; - } - - // 0x08 - if (_Value < 0) - { - g_dsp.r.sr |= SR_SIGN; - } - - // 0x10 - if (overS32) - { - g_dsp.r.sr |= SR_OVER_S32; - } - - // 0x20 - Checks if top bits of m are equal - if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3)) - { - g_dsp.r.sr |= SR_TOP2BITS; - } -} - -void Update_SR_LZ(bool value) -{ - if (value == true) - g_dsp.r.sr |= SR_LOGIC_ZERO; - else - g_dsp.r.sr &= ~SR_LOGIC_ZERO; -} - -inline int GetMultiplyModifier() -{ - return (g_dsp.r.sr & SR_MUL_MODIFY)?1:2; -} - -inline bool isCarry() { - return (g_dsp.r.sr & SR_CARRY) ? true : false; -} - -inline bool isOverflow() { - return (g_dsp.r.sr & SR_OVERFLOW) ? true : false; -} - -inline bool isOverS32() { - return (g_dsp.r.sr & SR_OVER_S32) ? true : false; -} - -inline bool isLess() { - return (!(g_dsp.r.sr & SR_OVERFLOW) != !(g_dsp.r.sr & SR_SIGN)); -} - -inline bool isZero() { - return (g_dsp.r.sr & SR_ARITH_ZERO) ? true : false; -} - -inline bool isLogicZero() { - return (g_dsp.r.sr & SR_LOGIC_ZERO) ? true : false; -} - -inline bool isConditionA() { - return (((g_dsp.r.sr & SR_OVER_S32) || (g_dsp.r.sr & SR_TOP2BITS)) && !(g_dsp.r.sr & SR_ARITH_ZERO)) ? true : false; -} - -//see DSPCore.h for flags -bool CheckCondition(u8 _Condition) -{ - switch (_Condition & 0xf) - { - case 0xf: // Always true. - return true; - case 0x0: // GE - Greater Equal - return !isLess(); - case 0x1: // L - Less - return isLess(); - case 0x2: // G - Greater - return !isLess() && !isZero(); - case 0x3: // LE - Less Equal - return isLess() || isZero(); - case 0x4: // NZ - Not Zero - return !isZero(); - case 0x5: // Z - Zero - return isZero(); - case 0x6: // NC - Not carry - return !isCarry(); - case 0x7: // C - Carry - return isCarry(); - case 0x8: // ? - Not over s32 - return !isOverS32(); - case 0x9: // ? - Over s32 - return isOverS32(); - case 0xa: // ? - return isConditionA(); - case 0xb: // ? - return !isConditionA(); - case 0xc: // LNZ - Logic Not Zero - return !isLogicZero(); - case 0xd: // LZ - Logic Zero - return isLogicZero(); - case 0xe: // 0 - Overflow - return isOverflow(); - default: - return true; - } -} - -} // namespace diff --git a/Source/Core/DSPCore/Src/DSPIntCCUtil.h b/Source/Core/DSPCore/Src/DSPIntCCUtil.h deleted file mode 100644 index 0684cea2ba..0000000000 --- a/Source/Core/DSPCore/Src/DSPIntCCUtil.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2003 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, bool carry = false, bool overflow = false, bool overS32 = false); -void Update_SR_Register64(s64 _Value, bool carry = false, bool overflow = false); -void Update_SR_LZ(bool value); - -inline bool isCarry(u64 val, u64 result) { - return (val>result); -} - -inline bool isCarry2(u64 val, u64 result) { - return (val>=result); -} - -inline bool isOverflow(s64 val1, s64 val2, s64 res) { - return ((val1 ^ res) & (val2 ^ res)) < 0; -} - -inline bool isOverS32(s64 acc) { - return (acc != (s32)acc) ? true : false; -} - -} // namespace - -#endif // _GDSP_CONDITION_CODES_H diff --git a/Source/Core/DSPCore/Src/DSPIntExtOps.cpp b/Source/Core/DSPCore/Src/DSPIntExtOps.cpp deleted file mode 100644 index 11eca9abac..0000000000 --- a/Source/Core/DSPCore/Src/DSPIntExtOps.cpp +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright (C) 2003 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 "DSPIntUtil.h" -#include "DSPMemoryMap.h" -#include "DSPIntExtOps.h" - -// Extended opcodes do not exist on their own. These opcodes can only be -// attached to opcodes that allow extending (8 (or 7) lower bits of opcode not used by -// opcode). Extended opcodes do not modify program counter $pc register. - -// Most of the suffixes increment or decrement one or more addressing registers -// (the first four, ARx). The increment/decrement is either 1, or the -// corresponding "index" register (the second four, IXx). The addressing -// registers will wrap in odd ways, dictated by the corresponding wrapping -// register, WR0-3. - -// Needs comments. -inline static void writeToBackLog(int i, int idx, u16 value) -{ - writeBackLog[i] = value; - writeBackLogIdx[i] = idx; -} - -namespace DSPInterpreter -{ - -namespace Ext -{ - -inline bool IsSameMemArea(u16 a, u16 b) -{ -//LM: tested on WII - if ((a>>10)==(b>>10)) - return true; - else - return false; -} - -// DR $arR -// xxxx xxxx 0000 01rr -// Decrement addressing register $arR. -void dr(const UDSPInstruction opc) { - writeToBackLog(0, opc & 0x3, dsp_decrement_addr_reg(opc & 0x3)); -} - -// IR $arR -// xxxx xxxx 0000 10rr -// Increment addressing register $arR. -void ir(const UDSPInstruction opc) { - writeToBackLog(0, opc & 0x3, dsp_increment_addr_reg(opc & 0x3)); -} - -// NR $arR -// xxxx xxxx 0000 11rr -// Add corresponding indexing register $ixR to addressing register $arR. -void nr(const UDSPInstruction opc) { - u8 reg = opc & 0x3; - - writeToBackLog(0, reg, dsp_increase_addr_reg(reg, (s16)g_dsp.r.ix[reg])); -} - -// MV $axD.D, $acS.S -// xxxx xxxx 0001 ddss -// Move value of $acS.S to the $axD.D. -void mv(const UDSPInstruction opc) -{ - u8 sreg = (opc & 0x3) + DSP_REG_ACL0; - u8 dreg = ((opc >> 2) & 0x3); - - switch(sreg) { - case DSP_REG_ACL0: - case DSP_REG_ACL1: - writeToBackLog(0, dreg + DSP_REG_AXL0, g_dsp.r.ac[sreg-DSP_REG_ACL0].l); - break; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - writeToBackLog(0, dreg + DSP_REG_AXL0, g_dsp.r.ac[sreg-DSP_REG_ACM0].m); - break; - } -} - -// S @$arD, $acS.S -// xxxx xxxx 001s s0dd -// Store value of $acS.S in the memory pointed by register $arD. -// Post increment register $arD. -void s(const UDSPInstruction opc) -{ - u8 dreg = opc & 0x3; - u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0; - - switch(sreg) { - case DSP_REG_ACL0: - case DSP_REG_ACL1: - dsp_dmem_write(g_dsp.r.ar[dreg], g_dsp.r.ac[sreg-DSP_REG_ACL0].l); - break; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - dsp_dmem_write(g_dsp.r.ar[dreg], g_dsp.r.ac[sreg-DSP_REG_ACM0].m); - break; - } - writeToBackLog(0, dreg, dsp_increment_addr_reg(dreg)); -} - -// SN @$arD, $acS.S -// xxxx xxxx 001s s1dd -// Store value of register $acS.S in the memory pointed by register $arD. -// Add indexing register $ixD to register $arD. -void sn(const UDSPInstruction opc) -{ - u8 dreg = opc & 0x3; - u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0; - - switch(sreg) { - case DSP_REG_ACL0: - case DSP_REG_ACL1: - dsp_dmem_write(g_dsp.r.ar[dreg], g_dsp.r.ac[sreg-DSP_REG_ACL0].l); - break; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - dsp_dmem_write(g_dsp.r.ar[dreg], g_dsp.r.ac[sreg-DSP_REG_ACM0].m); - break; - } - writeToBackLog(0, dreg, dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[dreg])); -} - -// L $axD.D, @$arS -// xxxx xxxx 01dd d0ss -// Load $axD.D/$acD.D with value from memory pointed by register $arS. -// Post increment register $arS. -void l(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x3; - u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0; - - if ((dreg >= DSP_REG_ACM0) && (g_dsp.r.sr & SR_40_MODE_BIT)) - { - u16 val = dsp_dmem_read(g_dsp.r.ar[sreg]); - writeToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) ? 0xFFFF : 0x0000); - writeToBackLog(1, dreg, val); - writeToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0); - writeToBackLog(3, sreg, dsp_increment_addr_reg(sreg)); - } - else - { - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[sreg])); - writeToBackLog(1, sreg, dsp_increment_addr_reg(sreg)); - } -} - -// LN $axD.D, @$arS -// xxxx xxxx 01dd d0ss -// Load $axD.D/$acD.D with value from memory pointed by register $arS. -// Add indexing register register $ixS to register $arS. -void ln(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x3; - u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0; - - if ((dreg >= DSP_REG_ACM0) && (g_dsp.r.sr & SR_40_MODE_BIT)) - { - u16 val = dsp_dmem_read(g_dsp.r.ar[sreg]); - writeToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) ? 0xFFFF : 0x0000); - writeToBackLog(1, dreg, val); - writeToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0); - writeToBackLog(3, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg])); - } - else - { - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[sreg])); - writeToBackLog(1, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg])); - } -} - -// LS $axD.D, $acS.m108 -// xxxx xxxx 10dd 000s -// Load register $axD.D with value from memory pointed by register -// $ar0. Store value from register $acS.m to memory location pointed by -// register $ar3. Increment both $ar0 and $ar3. -void ls(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - - dsp_dmem_write(g_dsp.r.ar[3], g_dsp.r.ac[sreg].m); - - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0])); - writeToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3)); - writeToBackLog(2, DSP_REG_AR0, dsp_increment_addr_reg(DSP_REG_AR0)); -} - - -// LSN $axD.D, $acS.m -// xxxx xxxx 10dd 010s -// Load register $axD.D with value from memory pointed by register -// $ar0. Store value from register $acS.m to memory location pointed by -// register $ar3. Add corresponding indexing register $ix0 to addressing -// register $ar0 and increment $ar3. -void lsn(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - - dsp_dmem_write(g_dsp.r.ar[3], g_dsp.r.ac[sreg].m); - - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0])); - writeToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3)); - writeToBackLog(2, DSP_REG_AR0, dsp_increase_addr_reg(DSP_REG_AR0, (s16)g_dsp.r.ix[0])); -} - -// LSM $axD.D, $acS.m -// xxxx xxxx 10dd 100s -// Load register $axD.D with value from memory pointed by register -// $ar0. Store value from register $acS.m to memory location pointed by -// register $ar3. Add corresponding indexing register $ix3 to addressing -// register $ar3 and increment $ar0. -void lsm(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - - dsp_dmem_write(g_dsp.r.ar[3], g_dsp.r.ac[sreg].m); - - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0])); - writeToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3])); - writeToBackLog(2, DSP_REG_AR0, dsp_increment_addr_reg(DSP_REG_AR0)); -} - -// LSMN $axD.D, $acS.m -// xxxx xxxx 10dd 110s -// Load register $axD.D with value from memory pointed by register -// $ar0. Store value from register $acS.m to memory location pointed by -// register $ar3. Add corresponding indexing register $ix0 to addressing -// register $ar0 and add corresponding indexing register $ix3 to addressing -// register $ar3. -void lsnm(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - - dsp_dmem_write(g_dsp.r.ar[3], g_dsp.r.ac[sreg].m); - - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0])); - writeToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3])); - writeToBackLog(2, DSP_REG_AR0, dsp_increase_addr_reg(DSP_REG_AR0, (s16)g_dsp.r.ix[0])); -} - -// SL $acS.m, $axD.D -// xxxx xxxx 10dd 001s -// Store value from register $acS.m to memory location pointed by register -// $ar0. Load register $axD.D with value from memory pointed by register -// $ar3. Increment both $ar0 and $ar3. -void sl(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - - dsp_dmem_write(g_dsp.r.ar[0], g_dsp.r.ac[sreg].m); - - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3])); - writeToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3)); - writeToBackLog(2, DSP_REG_AR0, dsp_increment_addr_reg(DSP_REG_AR0)); -} - -// SLN $acS.m, $axD.D -// xxxx xxxx 10dd 011s -// Store value from register $acS.m to memory location pointed by register -// $ar0. Load register $axD.D with value from memory pointed by register -// $ar3. Add corresponding indexing register $ix0 to addressing register $ar0 -// and increment $ar3. -void sln(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - - dsp_dmem_write(g_dsp.r.ar[0], g_dsp.r.ac[sreg].m); - - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3])); - writeToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3)); - writeToBackLog(2, DSP_REG_AR0, dsp_increase_addr_reg(DSP_REG_AR0, (s16)g_dsp.r.ix[0])); -} - -// SLM $acS.m, $axD.D -// xxxx xxxx 10dd 101s -// Store value from register $acS.m to memory location pointed by register -// $ar0. Load register $axD.D with value from memory pointed by register -// $ar3. Add corresponding indexing register $ix3 to addressing register $ar3 -// and increment $ar0. -void slm(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - - dsp_dmem_write(g_dsp.r.ar[0], g_dsp.r.ac[sreg].m); - - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3])); - writeToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3])); - writeToBackLog(2, DSP_REG_AR0, dsp_increment_addr_reg(DSP_REG_AR0)); -} - -// SLMN $acS.m, $axD.D -// xxxx xxxx 10dd 111s -// Store value from register $acS.m to memory location pointed by register -// $ar0. Load register $axD.D with value from memory pointed by register -// $ar3. Add corresponding indexing register $ix0 to addressing register $ar0 -// and add corresponding indexing register $ix3 to addressing register $ar3. -void slnm(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - - dsp_dmem_write(g_dsp.r.ar[0], g_dsp.r.ac[sreg].m); - - writeToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3])); - writeToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3])); - writeToBackLog(2, DSP_REG_AR0, dsp_increase_addr_reg(DSP_REG_AR0, (s16)g_dsp.r.ix[0])); -} - -// LD $ax0.d, $ax1.r, @$arS -// xxxx xxxx 11dr 00ss -// example for "nx'ld $AX0.L, $AX1.L, @$AR3" -// Loads the word pointed by AR0 to AX0.H, then loads the word pointed by AR3 to AX0.L. -// Increments AR0 and AR3. -// If AR0 and AR3 point into the same memory page (upper 6 bits of addr are the same -> games are not doing that!) -// then the value pointed by AR0 is loaded to BOTH AX0.H and AX0.L. -// If AR0 points into an invalid memory page (ie 0x2000), then AX0.H keeps its old value. (not implemented yet) -// If AR3 points into an invalid memory page, then AX0.L gets the same value as AX0.H. (not implemented yet) -void ld(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x1; - u8 rreg = (opc >> 4) & 0x1; - u8 sreg = opc & 0x3; - - if (sreg != DSP_REG_AR3) { - writeToBackLog(0, (dreg << 1) + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg])); - - if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3])) - writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[sreg])); - else - writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[3])); - - writeToBackLog(2, sreg, dsp_increment_addr_reg(sreg)); - } else { - writeToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r.ar[dreg])); - - if (IsSameMemArea(g_dsp.r.ar[dreg], g_dsp.r.ar[3])) - writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[dreg])); - else - writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[3])); - - writeToBackLog(2, dreg, dsp_increment_addr_reg(dreg)); - } - - writeToBackLog(3, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3)); -} - -// LDN $ax0.d, $ax1.r, @$arS -// xxxx xxxx 11dr 01ss -void ldn(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x1; - u8 rreg = (opc >> 4) & 0x1; - u8 sreg = opc & 0x3; - - if (sreg != DSP_REG_AR3) { - writeToBackLog(0, (dreg << 1) + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg])); - - if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3])) - writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[sreg])); - else - writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[3])); - - writeToBackLog(2, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg])); - } else { - writeToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r.ar[dreg])); - - if (IsSameMemArea(g_dsp.r.ar[dreg], g_dsp.r.ar[3])) - writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[dreg])); - else - writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[3])); - - writeToBackLog(2, dreg, dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[dreg])); - } - - writeToBackLog(3, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3)); -} - -// LDM $ax0.d, $ax1.r, @$arS -// xxxx xxxx 11dr 10ss -void ldm(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x1; - u8 rreg = (opc >> 4) & 0x1; - u8 sreg = opc & 0x3; - - if (sreg != DSP_REG_AR3) { - writeToBackLog(0, (dreg << 1) + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg])); - - if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3])) - writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[sreg])); - else - writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[3])); - - writeToBackLog(2, sreg, dsp_increment_addr_reg(sreg)); - } else { - writeToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r.ar[dreg])); - - if (IsSameMemArea(g_dsp.r.ar[dreg], g_dsp.r.ar[3])) - writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[dreg])); - else - writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[3])); - - writeToBackLog(2, dreg, dsp_increment_addr_reg(dreg)); - } - - writeToBackLog(3, DSP_REG_AR3, - dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3])); -} - -// LDNM $ax0.d, $ax1.r, @$arS -// xxxx xxxx 11dr 11ss -void ldnm(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x1; - u8 rreg = (opc >> 4) & 0x1; - u8 sreg = opc & 0x3; - - if (sreg != DSP_REG_AR3) { - writeToBackLog(0, (dreg << 1) + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg])); - - if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3])) - writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[sreg])); - else - writeToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[3])); - - writeToBackLog(2, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg])); - } else { - writeToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r.ar[dreg])); - - if (IsSameMemArea(g_dsp.r.ar[dreg], g_dsp.r.ar[3])) - writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[dreg])); - else - writeToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[3])); - - writeToBackLog(2, dreg, dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[dreg])); - } - - writeToBackLog(3, DSP_REG_AR3, - dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3])); -} - - -void nop(const UDSPInstruction opc) -{ -} - -} // end namespace ext -} // end namespace DSPInterpeter - - -// The ext ops are calculated in parallel with the actual op. That means that -// both the main op and the ext op see the same register state as input. The -// output is simple as long as the main and ext ops don't change the same -// register. If they do the output is the bitwise or of the result of both the -// main and ext ops. - -// The ext op are writing their output into the backlog which is -// being applied to the real registers after the main op was executed -void applyWriteBackLog() -{ - // always make sure to have an extra entry at the end w/ -1 to avoid - // infinitive loops - for (int i = 0; writeBackLogIdx[i] != -1; i++) { - dsp_op_write_reg(writeBackLogIdx[i], dsp_op_read_reg(writeBackLogIdx[i]) | writeBackLog[i]); - // Clear back log - writeBackLogIdx[i] = -1; - } -} - -// This function is being called in the main op after all input regs were read -// and before it writes into any regs. This way we can always use bitwise or to -// apply the ext command output, because if the main op didn't change the value -// then 0 | ext output = ext output and if it did then bitwise or is still the -// right thing to do -void zeroWriteBackLog() -{ - // always make sure to have an extra entry at the end w/ -1 to avoid - // infinitive loops - for (int i = 0; writeBackLogIdx[i] != -1; i++) { - dsp_op_write_reg(writeBackLogIdx[i], 0); - } -} - -//needed for 0x3... cases when main and extended are modifying the same ACC -//games are not doing that + in motorola (similar dsp) dox this is forbidden to do -//ex. corner case -> 0x3060: main opcode modifies .m, and extended .l -> .l shoudnt be zeroed because of .m write... -void zeroWriteBackLogPreserveAcc(u8 acc) -{ - for (int i = 0; writeBackLogIdx[i] != -1; i++) { - - // acc0 - if ((acc == 0) && - ((writeBackLogIdx[i] == DSP_REG_ACL0) || (writeBackLogIdx[i] == DSP_REG_ACM0) || (writeBackLogIdx[i] == DSP_REG_ACH0))) - continue; - - // acc1 - if ((acc == 1) && - ((writeBackLogIdx[i] == DSP_REG_ACL1) || (writeBackLogIdx[i] == DSP_REG_ACM1) || (writeBackLogIdx[i] == DSP_REG_ACH1))) - continue; - - dsp_op_write_reg(writeBackLogIdx[i], 0); - } -} diff --git a/Source/Core/DSPCore/Src/DSPIntExtOps.h b/Source/Core/DSPCore/Src/DSPIntExtOps.h deleted file mode 100644 index 46b809ca14..0000000000 --- a/Source/Core/DSPCore/Src/DSPIntExtOps.h +++ /dev/null @@ -1,64 +0,0 @@ -/*==================================================================== - - filename: opcodes.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 _GDSP_EXT_OP_H -#define _GDSP_EXT_OP_H - -#include "DSPTables.h" - -// Extended opcode support. -// Many opcode have the lower 0xFF (some only 0x7f) free - there, an opcode extension -// can be stored. - -namespace DSPInterpreter -{ -namespace Ext -{ -void l(const UDSPInstruction opc); -void ln(const UDSPInstruction opc); -void ls(const UDSPInstruction opc); -void lsn(const UDSPInstruction opc); -void lsm(const UDSPInstruction opc); -void lsnm(const UDSPInstruction opc); -void sl(const UDSPInstruction opc); -void sln(const UDSPInstruction opc); -void slm(const UDSPInstruction opc); -void slnm(const UDSPInstruction opc); -void s(const UDSPInstruction opc); -void sn(const UDSPInstruction opc); -void ld(const UDSPInstruction opc); -void ldn(const UDSPInstruction opc); -void ldm(const UDSPInstruction opc); -void ldnm(const UDSPInstruction opc); -void mv(const UDSPInstruction opc); -void dr(const UDSPInstruction opc); -void ir(const UDSPInstruction opc); -void nr(const UDSPInstruction opc); -void nop(const UDSPInstruction opc); - -} // end namespace Ext -} // end namespace DSPinterpeter - -#endif diff --git a/Source/Core/DSPCore/Src/DSPIntUtil.h b/Source/Core/DSPCore/Src/DSPIntUtil.h deleted file mode 100644 index 712d79fdf8..0000000000 --- a/Source/Core/DSPCore/Src/DSPIntUtil.h +++ /dev/null @@ -1,386 +0,0 @@ -/*==================================================================== - - filename: gdsp_opcodes_helper.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_INT_UTIL_H -#define _DSP_INT_UTIL_H - -#include "Common.h" - -#include "DSPInterpreter.h" -#include "DSPCore.h" -#include "DSPMemoryMap.h" -#include "DSPStacks.h" - - -// --------------------------------------------------------------------------------------- -// --- SR -// --------------------------------------------------------------------------------------- - -inline void dsp_SR_set_flag(int flag) -{ - g_dsp.r.sr |= flag; -} - -inline bool dsp_SR_is_flag_set(int flag) -{ - return (g_dsp.r.sr & flag) != 0; -} - -// --------------------------------------------------------------------------------------- -// --- AR increments, decrements -// --------------------------------------------------------------------------------------- - -inline u16 dsp_increase_addr_reg(u16 reg, s16 _ix) -{ - u32 ar = g_dsp.r.ar[reg]; - u32 wr = g_dsp.r.wr[reg]; - s32 ix = _ix; - - u32 mx = (wr | 1) << 1; - u32 nar = ar + ix; - u32 dar = (nar ^ ar ^ ix) & mx; - - if (ix >= 0) - { - if (dar > wr) //overflow - nar -= wr + 1; - } - else - { - if ((((nar + wr + 1) ^ nar) & dar) <= wr) //underflow or below min for mask - nar += wr + 1; - } - return nar; -} - -inline u16 dsp_decrease_addr_reg(u16 reg, s16 _ix) -{ - u32 ar = g_dsp.r.ar[reg]; - u32 wr = g_dsp.r.wr[reg]; - s32 ix = _ix; - - u32 mx = (wr | 1) << 1; - u32 nar = ar - ix; - u32 dar = (nar ^ ar ^ ~ix) & mx; - - if ((u32)ix > 0xFFFF8000) //(ix < 0 && ix != -0x8000) - { - if (dar > wr) //overflow - nar -= wr + 1; - } - else - { - if ((((nar + wr + 1) ^ nar) & dar) <= wr) //underflow or below min for mask - nar += wr + 1; - } - return nar; -} - -inline u16 dsp_increment_addr_reg(u16 reg) -{ - u32 ar = g_dsp.r.ar[reg]; - u32 wr = g_dsp.r.wr[reg]; - - u32 nar = ar + 1; - - if ((nar ^ ar) > ((wr | 1) << 1)) - nar -= wr + 1; - return nar; -} - -inline u16 dsp_decrement_addr_reg(u16 reg) -{ - u32 ar = g_dsp.r.ar[reg]; - u32 wr = g_dsp.r.wr[reg]; - - u32 nar = ar + wr; - - if (((nar ^ ar) & ((wr | 1) << 1)) > wr) - nar -= wr + 1; - return nar; -} - - -// --------------------------------------------------------------------------------------- -// --- reg -// --------------------------------------------------------------------------------------- - -inline u16 dsp_op_read_reg(int reg) -{ - switch (reg & 0x1f) { - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - return dsp_reg_load_stack(reg - DSP_REG_ST0); - case DSP_REG_AR0: - case DSP_REG_AR1: - case DSP_REG_AR2: - case DSP_REG_AR3: - return g_dsp.r.ar[reg - DSP_REG_AR0]; - case DSP_REG_IX0: - case DSP_REG_IX1: - case DSP_REG_IX2: - case DSP_REG_IX3: - return g_dsp.r.ix[reg - DSP_REG_IX0]; - case DSP_REG_WR0: - case DSP_REG_WR1: - case DSP_REG_WR2: - case DSP_REG_WR3: - return g_dsp.r.wr[reg - DSP_REG_WR0]; - case DSP_REG_ACH0: - case DSP_REG_ACH1: - return g_dsp.r.ac[reg - DSP_REG_ACH0].h; - case DSP_REG_CR: return g_dsp.r.cr; - case DSP_REG_SR: return g_dsp.r.sr; - case DSP_REG_PRODL: return g_dsp.r.prod.l; - case DSP_REG_PRODM: return g_dsp.r.prod.m; - case DSP_REG_PRODH: return g_dsp.r.prod.h; - case DSP_REG_PRODM2: return g_dsp.r.prod.m2; - case DSP_REG_AXL0: - case DSP_REG_AXL1: - return g_dsp.r.ax[reg - DSP_REG_AXL0].l; - case DSP_REG_AXH0: - case DSP_REG_AXH1: - return g_dsp.r.ax[reg - DSP_REG_AXH0].h; - case DSP_REG_ACL0: - case DSP_REG_ACL1: - return g_dsp.r.ac[reg - DSP_REG_ACL0].l; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - return g_dsp.r.ac[reg - DSP_REG_ACM0].m; - default: - _assert_msg_(DSP_INT, 0, "cannot happen"); - return 0; - } -} - -inline void dsp_op_write_reg(int reg, u16 val) -{ - switch (reg & 0x1f) { - // 8-bit sign extended registers. Should look at prod.h too... - case DSP_REG_ACH0: - case DSP_REG_ACH1: - // sign extend from the bottom 8 bits. - g_dsp.r.ac[reg-DSP_REG_ACH0].h = (u16)(s16)(s8)(u8)val; - break; - - // Stack registers. - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - dsp_reg_store_stack(reg - DSP_REG_ST0, val); - break; - - case DSP_REG_AR0: - case DSP_REG_AR1: - case DSP_REG_AR2: - case DSP_REG_AR3: - g_dsp.r.ar[reg - DSP_REG_AR0] = val; - break; - case DSP_REG_IX0: - case DSP_REG_IX1: - case DSP_REG_IX2: - case DSP_REG_IX3: - g_dsp.r.ix[reg - DSP_REG_IX0] = val; - break; - case DSP_REG_WR0: - case DSP_REG_WR1: - case DSP_REG_WR2: - case DSP_REG_WR3: - g_dsp.r.wr[reg - DSP_REG_WR0] = val; - break; - case DSP_REG_CR: g_dsp.r.cr = val; break; - case DSP_REG_SR: g_dsp.r.sr = val; break; - case DSP_REG_PRODL: g_dsp.r.prod.l = val; break; - case DSP_REG_PRODM: g_dsp.r.prod.m = val; break; - case DSP_REG_PRODH: g_dsp.r.prod.h = val; break; - case DSP_REG_PRODM2: g_dsp.r.prod.m2 = val; break; - case DSP_REG_AXL0: - case DSP_REG_AXL1: - g_dsp.r.ax[reg - DSP_REG_AXL0].l = val; - break; - case DSP_REG_AXH0: - case DSP_REG_AXH1: - g_dsp.r.ax[reg - DSP_REG_AXH0].h = val; - break; - case DSP_REG_ACL0: - case DSP_REG_ACL1: - g_dsp.r.ac[reg - DSP_REG_ACL0].l = val; - break; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - g_dsp.r.ac[reg - DSP_REG_ACM0].m = val; - break; - } -} - -inline void dsp_conditional_extend_accum(int reg) -{ - switch (reg) - { - case DSP_REG_ACM0: - case DSP_REG_ACM1: - if (g_dsp.r.sr & SR_40_MODE_BIT) - { - // Sign extend into whole accum. - u16 val = g_dsp.r.ac[reg-DSP_REG_ACM0].m; - g_dsp.r.ac[reg - DSP_REG_ACM0].h = (val & 0x8000) ? 0xFFFF : 0x0000; - g_dsp.r.ac[reg - DSP_REG_ACM0].l = 0; - } - } -} - -// --------------------------------------------------------------------------------------- -// --- prod -// --------------------------------------------------------------------------------------- - -inline s64 dsp_get_long_prod() -{ -#if PROFILE - ProfilerAddDelta(g_dsp.err_pc, 1); -#endif - - s64 val = (s8)(u8)g_dsp.r.prod.h; - val <<= 32; - s64 low_prod = g_dsp.r.prod.m; - low_prod += g_dsp.r.prod.m2; - low_prod <<= 16; - low_prod |= g_dsp.r.prod.l; - val += low_prod; - return val; -} - -inline s64 dsp_get_long_prod_round_prodl() -{ - s64 prod = dsp_get_long_prod(); - - if (prod & 0x10000) - prod = (prod + 0x8000) & ~0xffff; - else - prod = (prod + 0x7fff) & ~0xffff; - - return prod; -} - -// For accurate emulation, this is wrong - but the real prod registers behave -// in completely bizarre ways. Not needed to emulate them correctly for game ucodes. -inline void dsp_set_long_prod(s64 val) -{ -#if PROFILE - ProfilerAddDelta(g_dsp.err_pc, 1); -#endif - - g_dsp.r.prod.l = (u16)val; - val >>= 16; - g_dsp.r.prod.m = (u16)val; - val >>= 16; - g_dsp.r.prod.h = /*(s16)(s8)*/(u8)val;//todo: check expansion - g_dsp.r.prod.m2 = 0; -} - -// --------------------------------------------------------------------------------------- -// --- ACC - main accumulators (40-bit) -// --------------------------------------------------------------------------------------- - -inline s64 dsp_get_long_acc(int reg) -{ -#if PROFILE - ProfilerAddDelta(g_dsp.err_pc, 1); -#endif - - s64 high = (s64)(s8)g_dsp.r.ac[reg].h << 32; - u32 mid_low = ((u32)g_dsp.r.ac[reg].m << 16) | g_dsp.r.ac[reg].l; - return high | mid_low; -} - -inline void dsp_set_long_acc(int _reg, s64 val) -{ -#if PROFILE - ProfilerAddDelta(g_dsp.err_pc, 1); -#endif - - g_dsp.r.ac[_reg].l = (u16)val; - val >>= 16; - g_dsp.r.ac[_reg].m = (u16)val; - val >>= 16; - g_dsp.r.ac[_reg].h = (u16)(s16)(s8)(u8)val; -} - -inline s64 dsp_convert_long_acc(s64 val) // s64 -> s40 -{ - return ((s64)(s8)(val >> 32))<<32 | (u32)val; -} - -inline s64 dsp_round_long_acc(s64 val) -{ - if (val & 0x10000) - val = (val + 0x8000) & ~0xffff; - else - val = (val + 0x7fff) & ~0xffff; - - return val; -} - -inline s16 dsp_get_acc_l(int _reg) -{ - return g_dsp.r.ac[_reg].l; -} - -inline s16 dsp_get_acc_m(int _reg) -{ - return g_dsp.r.ac[_reg].m; -} - -inline s16 dsp_get_acc_h(int _reg) -{ - return g_dsp.r.ac[_reg].h; -} - -// --------------------------------------------------------------------------------------- -// --- AX - extra accumulators (32-bit) -// --------------------------------------------------------------------------------------- - -inline s32 dsp_get_long_acx(int _reg) -{ -#if PROFILE - ProfilerAddDelta(g_dsp.err_pc, 1); -#endif - - return ((u32)g_dsp.r.ax[_reg].h << 16) | g_dsp.r.ax[_reg].l; -} - -inline s16 dsp_get_ax_l(int _reg) -{ - return (s16)g_dsp.r.ax[_reg].l; -} - -inline s16 dsp_get_ax_h(int _reg) -{ - return (s16)g_dsp.r.ax[_reg].h; -} - -#endif diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.cpp b/Source/Core/DSPCore/Src/DSPInterpreter.cpp deleted file mode 100644 index 56e1834b9f..0000000000 --- a/Source/Core/DSPCore/Src/DSPInterpreter.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/*==================================================================== - - 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 "DSPTables.h" -#include "DSPHost.h" -#include "DSPCore.h" -#include "DSPAnalyzer.h" - -#include "DSPHWInterface.h" -#include "DSPIntUtil.h" - -namespace DSPInterpreter { - -volatile u32 gdsp_running; - -// NOTE: These have nothing to do with g_dsp.r[DSP_REG_CR]. - -// Hm, should instructions that change CR use this? Probably not (but they -// should call UpdateCachedCR()) -void WriteCR(u16 val) -{ - // reset - if (val & 1) - { - DSPCore_Reset(); - val &= ~1; - } - // init - can reset and init be done at the same time? - else if (val == 4) - { - // this looks like a hack! OSInitAudioSystem ucode - // should send this mail - not dsp core itself - gdsp_mbox_write_h(GDSP_MBOX_DSP, 0x8054); - gdsp_mbox_write_l(GDSP_MBOX_DSP, 0x4348); - val |= 0x800; - } - - // update cr - g_dsp.cr = val; -} - -// Hm, should instructions that read CR use this? (Probably not). -u16 ReadCR() -{ - if (g_dsp.pc & 0x8000) - { - g_dsp.cr |= 0x800; - } - else - { - g_dsp.cr &= ~0x800; - } - - return g_dsp.cr; -} - -void Step() -{ - DSPCore_CheckExceptions(); - - g_dsp.step_counter++; - -#if PROFILE - g_dsp.err_pc = g_dsp.pc; - - ProfilerAddDelta(g_dsp.err_pc, 1); - if (g_dsp.step_counter == 1) - { - ProfilerInit(); - } - - if ((g_dsp.step_counter & 0xFFFFF) == 0) - { - ProfilerDump(g_dsp.step_counter); - } -#endif - - u16 opc = dsp_fetch_code(); - ExecuteInstruction(UDSPInstruction(opc)); - - if (DSPAnalyzer::code_flags[g_dsp.pc - 1] & DSPAnalyzer::CODE_LOOP_END) - HandleLoop(); -} - -// Used by thread mode. -//void Run() -//{ -// int checkInterrupt = 0; -// gdsp_running = true; -// while (!(g_dsp.cr & CR_HALT) && gdsp_running) -// { -// if (jit) -// jit->RunForCycles(1); -// else { -// // Automatically let the other threads work if we're idle skipping -// if(DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP) -// Common::YieldCPU(); -// -// Step(); -// -// // Turns out the less you check for external interrupts, the more -// // sound you hear, and it becomes slower -// checkInterrupt++; -// if(checkInterrupt == 500) { // <-- Arbitrary number. TODO: tweak -// DSPCore_CheckExternalInterrupt(); -// checkInterrupt = 0; -// } -// } -// } -// gdsp_running = false; -//} - -// This one has basic idle skipping, and checks breakpoints. -int RunCyclesDebug(int cycles) -{ - // First, let's run a few cycles with no idle skipping so that things can progress a bit. - for (int i = 0; i < 8; i++) - { - if (g_dsp.cr & CR_HALT) - return 0; - if (dsp_breakpoints.IsAddressBreakPoint(g_dsp.pc)) - { - DSPCore_SetState(DSPCORE_STEPPING); - return cycles; - } - Step(); - cycles--; - if (cycles < 0) - return 0; - } - - // In thread mode, process external interrupts - if (g_dsp.external_interrupt_waiting) - { - DSPCore_CheckExternalInterrupt(); - DSPCore_CheckExceptions(); - DSPCore_SetExternalInterrupt(false); - } - - while (true) - { - // Next, let's run a few cycles with idle skipping, so that we can skip - // idle loops. - for (int i = 0; i < 8; i++) - { - if (g_dsp.cr & CR_HALT) - return 0; - if (dsp_breakpoints.IsAddressBreakPoint(g_dsp.pc)) - { - DSPCore_SetState(DSPCORE_STEPPING); - return cycles; - } - // Idle skipping. - if (DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP) - return 0; - Step(); - cycles--; - if (cycles < 0) - return 0; - } - - // Now, lets run some more without idle skipping. - for (int i = 0; i < 200; i++) - { - if (dsp_breakpoints.IsAddressBreakPoint(g_dsp.pc)) - { - DSPCore_SetState(DSPCORE_STEPPING); - return cycles; - } - Step(); - cycles--; - if (cycles < 0) - return 0; - - // We don't bother directly supporting pause - if the main emu pauses, - // it just won't call this function anymore. - } - } -} - -// Used by non-thread mode. Meant to be efficient. -int RunCycles(int cycles) -{ - // First, let's run a few cycles with no idle skipping so that things can - // progress a bit. - for (int i = 0; i < 8; i++) - { - if (g_dsp.cr & CR_HALT) - return 0; - Step(); - cycles--; - if (cycles < 0) - return 0; - } - - // In thread mode, process external interrupts - if (g_dsp.external_interrupt_waiting) - { - DSPCore_CheckExternalInterrupt(); - DSPCore_CheckExceptions(); - DSPCore_SetExternalInterrupt(false); - } - - while (true) - { - // Next, let's run a few cycles with idle skipping, so that we can skip - // idle loops. - for (int i = 0; i < 8; i++) - { - if (g_dsp.cr & CR_HALT) - return 0; - // Idle skipping. - if (DSPAnalyzer::code_flags[g_dsp.pc] & DSPAnalyzer::CODE_IDLE_SKIP) - return 0; - Step(); - cycles--; - if (cycles < 0) - return 0; - } - - // Now, lets run some more without idle skipping. - for (int i = 0; i < 200; i++) - { - Step(); - cycles--; - if (cycles < 0) - return 0; - // We don't bother directly supporting pause - if the main emu pauses, - // it just won't call this function anymore. - } - } -} - -void Stop() -{ - gdsp_running = false; -} - -} // namespace diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.h b/Source/Core/DSPCore/Src/DSPInterpreter.h deleted file mode 100644 index 35db43f5f2..0000000000 --- a/Source/Core/DSPCore/Src/DSPInterpreter.h +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (C) 2003 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(); - -// See: DspIntBranch.cpp -void HandleLoop(); - -// 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 orr(const UDSPInstruction opc); -void andc(const UDSPInstruction opc); -void orc(const UDSPInstruction opc); -void xorc(const UDSPInstruction opc); -void notc(const UDSPInstruction opc); -void lsrnrx(const UDSPInstruction opc); -void asrnrx(const UDSPInstruction opc); -void lsrnr(const UDSPInstruction opc); -void asrnr(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 subarn(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); -void srbith(const UDSPInstruction opc); -void mulaxh(const UDSPInstruction opc); -void tstprod(const UDSPInstruction opc); -void abs(const UDSPInstruction opc); - -} // namespace - -#endif // _DSPINTERPRETER_H diff --git a/Source/Core/DSPCore/Src/DSPMemoryMap.cpp b/Source/Core/DSPCore/Src/DSPMemoryMap.cpp deleted file mode 100644 index 408cb48465..0000000000 --- a/Source/Core/DSPCore/Src/DSPMemoryMap.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/*==================================================================== - - filename: gdsp_memory.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 "DSPInterpreter.h" -#include "DSPMemoryMap.h" -#include "DSPHWInterface.h" -#include "DSPCore.h" - -u16 dsp_imem_read(u16 addr) -{ - switch (addr >> 12) - { - case 0: // 0xxx IRAM - return g_dsp.iram[addr & DSP_IRAM_MASK]; - - case 8: // 8xxx IROM - contains code to receive code for IRAM, and a bunch of mixing loops. - return g_dsp.irom[addr & DSP_IROM_MASK]; - - default: // Unmapped/non-existing memory - ERROR_LOG(DSPLLE, "%04x DSP ERROR: Executing from invalid (%04x) memory", g_dsp.pc, addr); - return 0; - } -} - -u16 dsp_dmem_read(u16 addr) -{ - switch (addr >> 12) - { - case 0x0: // 0xxx DRAM - return g_dsp.dram[addr & DSP_DRAM_MASK]; - - case 0x1: // 1xxx COEF - DEBUG_LOG(DSPLLE, "%04x : Coef Read @ %04x", g_dsp.pc, addr); - return g_dsp.coef[addr & DSP_COEF_MASK]; - - case 0xf: // Fxxx HW regs - return gdsp_ifx_read(addr); - - default: // Unmapped/non-existing memory - ERROR_LOG(DSPLLE, "%04x DSP ERROR: Read from UNKNOWN (%04x) memory", g_dsp.pc, addr); - return 0; - } -} - -void dsp_dmem_write(u16 addr, u16 val) -{ - switch (addr >> 12) - { - case 0x0: // 0xxx DRAM - g_dsp.dram[addr & DSP_DRAM_MASK] = val; - break; - - case 0xf: // Fxxx HW regs - gdsp_ifx_write(addr, val); - break; - - default: // Unmapped/non-existing memory - ERROR_LOG(DSPLLE, "%04x DSP ERROR: Write to UNKNOWN (%04x) memory", g_dsp.pc, addr); - break; - } -} diff --git a/Source/Core/DSPCore/Src/DSPMemoryMap.h b/Source/Core/DSPCore/Src/DSPMemoryMap.h deleted file mode 100644 index 8aa0d77647..0000000000 --- a/Source/Core/DSPCore/Src/DSPMemoryMap.h +++ /dev/null @@ -1,55 +0,0 @@ -/*==================================================================== - - filename: gdsp_memory.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 _GDSP_MEMORY_H -#define _GDSP_MEMORY_H - -#include "Common.h" -#include "DSPInterpreter.h" -#include "DSPCore.h" - -u16 dsp_imem_read(u16 addr); -void dsp_dmem_write(u16 addr, u16 val); -u16 dsp_dmem_read(u16 addr); - -inline u16 dsp_fetch_code() -{ - u16 opc = dsp_imem_read(g_dsp.pc); - - g_dsp.pc++; - return opc; -} - -inline u16 dsp_peek_code() -{ - return dsp_imem_read(g_dsp.pc); -} - -inline void dsp_skip_inst() -{ - g_dsp.pc += opTable[dsp_peek_code()]->size; -} - -#endif diff --git a/Source/Core/DSPCore/Src/DSPStacks.cpp b/Source/Core/DSPCore/Src/DSPStacks.cpp deleted file mode 100644 index 5bdae0241f..0000000000 --- a/Source/Core/DSPCore/Src/DSPStacks.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/*==================================================================== - - filename: gdsp_registers.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 "DSPCore.h" -#include "DSPStacks.h" - -// Stacks. The stacks are outside the DSP RAM, in dedicated hardware. - -void dsp_reg_stack_push(int stack_reg) -{ - g_dsp.reg_stack_ptr[stack_reg]++; - g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; - g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r.st[stack_reg]; -} - -void dsp_reg_stack_pop(int stack_reg) -{ - g_dsp.r.st[stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]; - g_dsp.reg_stack_ptr[stack_reg]--; - g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; -} - -void dsp_reg_store_stack(int stack_reg, u16 val) -{ - dsp_reg_stack_push(stack_reg); - g_dsp.r.st[stack_reg] = val; -} - -u16 dsp_reg_load_stack(int stack_reg) -{ - u16 val = g_dsp.r.st[stack_reg]; - dsp_reg_stack_pop(stack_reg); - return val; -} diff --git a/Source/Core/DSPCore/Src/DSPStacks.h b/Source/Core/DSPCore/Src/DSPStacks.h deleted file mode 100644 index 1a5b9e872c..0000000000 --- a/Source/Core/DSPCore/Src/DSPStacks.h +++ /dev/null @@ -1,34 +0,0 @@ -/*==================================================================== - - filename: gdsp_registers.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 _DSP_STACKS_H -#define _DSP_STACKS_H - -#include "Common.h" - -void dsp_reg_store_stack(int stack_reg, u16 val); -u16 dsp_reg_load_stack(int stack_reg); - -#endif diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp deleted file mode 100644 index 80da03c190..0000000000 --- a/Source/Core/DSPCore/Src/DSPTables.cpp +++ /dev/null @@ -1,568 +0,0 @@ -// Copyright (C) 2003 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) - -#include "Common.h" -#include "DSPTables.h" - -#include "DSPInterpreter.h" -#include "DSPIntExtOps.h" -#include "DSPEmitter.h" - -void nop(const UDSPInstruction opc) -{ - // The real nop is 0. Anything else is bad. - if (opc) - DSPInterpreter::unknown(opc); -} - -const DSPOPCTemplate opcodes[] = -{ - {"NOP", 0x0000, 0xfffc, nop, &DSPEmitter::nop, 1, 0, {}, false, false, false, false, false}, - - {"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, &DSPEmitter::dar, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, - {"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, &DSPEmitter::iar, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, - {"SUBARN", 0x000c, 0xfffc, DSPInterpreter::subarn, &DSPEmitter::subarn, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, - {"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, &DSPEmitter::addarn, 1, 2, {{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}}, false, false, false, false, false}, - - {"HALT", 0x0021, 0xffff, DSPInterpreter::halt, &DSPEmitter::halt, 1, 0, {}, false, true, true, false, false}, - - {"RETGE", 0x02d0, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETL", 0x02d1, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETG", 0x02d2, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETLE", 0x02d3, 0xffff, DSPInterpreter::ret, NULL/*&DSPEmitter::ret*/, 1, 0, {}, false, true, false, true, false}, - {"RETNZ", 0x02d4, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETZ", 0x02d5, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETNC", 0x02d6, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETC", 0x02d7, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETx8", 0x02d8, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETx9", 0x02d9, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETxA", 0x02da, 0xffff, DSPInterpreter::ret, NULL/*&DSPEmitter::ret*/, 1, 0, {}, false, true, false, true, false}, - {"RETxB", 0x02db, 0xffff, DSPInterpreter::ret, NULL/*&DSPEmitter::ret*/, 1, 0, {}, false, true, false, true, false}, - {"RETLNZ", 0x02dc, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETLZ", 0x02dd, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RETO", 0x02de, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, false, true, false}, - {"RET", 0x02df, 0xffff, DSPInterpreter::ret, &DSPEmitter::ret, 1, 0, {}, false, true, true, false, false}, - - {"RTI", 0x02ff, 0xffff, DSPInterpreter::rti, &DSPEmitter::rti, 1, 0, {}, false, true, true, false, false}, - - {"CALLGE", 0x02b0, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLL", 0x02b1, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLG", 0x02b2, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLLE", 0x02b3, 0xffff, DSPInterpreter::call, NULL/*&DSPEmitter::call*/, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLNZ", 0x02b4, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLZ", 0x02b5, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLNC", 0x02b6, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLC", 0x02b7, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLx8", 0x02b8, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLx9", 0x02b9, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLxA", 0x02ba, 0xffff, DSPInterpreter::call, NULL/*&DSPEmitter::call*/, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLxB", 0x02bb, 0xffff, DSPInterpreter::call, NULL/*&DSPEmitter::call*/, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLLNZ", 0x02bc, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLLZ", 0x02bd, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALLO", 0x02be, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"CALL", 0x02bf, 0xffff, DSPInterpreter::call, &DSPEmitter::call, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, true, true, false}, - - {"IFGE", 0x0270, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFL", 0x0271, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFG", 0x0272, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFLE", 0x0273, 0xffff, DSPInterpreter::ifcc, NULL/*&DSPEmitter::ifcc*/, 1, 0, {}, false, true, false, true, false}, - {"IFNZ", 0x0274, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFZ", 0x0275, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFNC", 0x0276, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFC", 0x0277, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFx8", 0x0278, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFx9", 0x0279, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFxA", 0x027a, 0xffff, DSPInterpreter::ifcc, NULL/*&DSPEmitter::ifcc*/, 1, 0, {}, false, true, false, true, false}, - {"IFxB", 0x027b, 0xffff, DSPInterpreter::ifcc, NULL/*&DSPEmitter::ifcc*/, 1, 0, {}, false, true, false, true, false}, - {"IFLNZ", 0x027c, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFLZ", 0x027d, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IFO", 0x027e, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, false, true, false}, - {"IF", 0x027f, 0xffff, DSPInterpreter::ifcc, &DSPEmitter::ifcc, 1, 0, {}, false, true, true, true, false}, - - {"JGE", 0x0290, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JL", 0x0291, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JG", 0x0292, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JLE", 0x0293, 0xffff, DSPInterpreter::jcc, NULL/*&DSPEmitter::jcc*/, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JNZ", 0x0294, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JZ", 0x0295, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JNC", 0x0296, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JC", 0x0297, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JMPx8", 0x0298, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JMPx9", 0x0299, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JMPxA", 0x029a, 0xffff, DSPInterpreter::jcc, NULL/*&DSPEmitter::jcc*/, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JMPxB", 0x029b, 0xffff, DSPInterpreter::jcc, NULL/*&DSPEmitter::jcc*/, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JLNZ", 0x029c, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JO", 0x029e, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, &DSPEmitter::jcc, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, true, true, false}, - - {"JRGE", 0x1700, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRL", 0x1701, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRG", 0x1702, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRLE", 0x1703, 0xff1f, DSPInterpreter::jmprcc, NULL/*&DSPEmitter::jmprcc*/, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRNZ", 0x1704, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRZ", 0x1705, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRNC", 0x1706, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRC", 0x1707, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JMPRx8", 0x1708, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JMPRx9", 0x1709, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JMPRxA", 0x170a, 0xff1f, DSPInterpreter::jmprcc, NULL/*&DSPEmitter::jmprcc*/, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JMPRxB", 0x170b, 0xff1f, DSPInterpreter::jmprcc, NULL/*&DSPEmitter::jmprcc*/, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRLNZ", 0x170c, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRLZ", 0x170d, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JRO", 0x170e, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, false, false}, - {"JMPR", 0x170f, 0xff1f, DSPInterpreter::jmprcc, &DSPEmitter::jmprcc, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, true, false, false}, - - {"CALLRGE", 0x1710, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRL", 0x1711, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRG", 0x1712, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRLE", 0x1713, 0xff1f, DSPInterpreter::callr, NULL/*&DSPEmitter::callr*/, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRNZ", 0x1714, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRZ", 0x1715, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRNC", 0x1716, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRC", 0x1717, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRx8", 0x1718, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRx9", 0x1719, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRxA", 0x171a, 0xff1f, DSPInterpreter::callr, NULL/*&DSPEmitter::callr*/, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRxB", 0x171b, 0xff1f, DSPInterpreter::callr, NULL/*&DSPEmitter::callr*/, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRLNZ",0x171c, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRLZ", 0x171d, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLRO", 0x171e, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, false, true, false}, - {"CALLR", 0x171f, 0xff1f, DSPInterpreter::callr, &DSPEmitter::callr, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true, true, true, false}, - - {"SBCLR", 0x1200, 0xff00, DSPInterpreter::sbclr, &DSPEmitter::sbclr, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false, false, false, false}, - {"SBSET", 0x1300, 0xff00, DSPInterpreter::sbset, &DSPEmitter::sbset, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false, false, false, false}, - - {"LSL", 0x1400, 0xfec0, DSPInterpreter::lsl, &DSPEmitter::lsl, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, - {"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, &DSPEmitter::lsr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, - {"ASL", 0x1480, 0xfec0, DSPInterpreter::asl, &DSPEmitter::asl, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, - {"ASR", 0x14c0, 0xfec0, DSPInterpreter::asr, &DSPEmitter::asr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false, false, false, true}, - - {"LSRN", 0x02ca, 0xffff, DSPInterpreter::lsrn, &DSPEmitter::lsrn, 1, 0, {}, false, false, false, false, true}, // discovered by ector! - {"ASRN", 0x02cb, 0xffff, DSPInterpreter::asrn, &DSPEmitter::asrn, 1, 0, {}, false, false, false, false, true}, // discovered by ector! - - {"LRI", 0x0080, 0xffe0, DSPInterpreter::lri, &DSPEmitter::lri, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, false}, - {"LR", 0x00c0, 0xffe0, DSPInterpreter::lr, &DSPEmitter::lr, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}}, false, false, false, true, false}, - {"SR", 0x00e0, 0xffe0, DSPInterpreter::sr, &DSPEmitter::sr, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}}, false, false, false, true, false}, - - {"MRR", 0x1c00, 0xfc00, DSPInterpreter::mrr, &DSPEmitter::mrr, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}}, false, false, false, false, false}, - - {"SI", 0x1600, 0xff00, DSPInterpreter::si, &DSPEmitter::si, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, false}, - - {"ADDIS", 0x0400, 0xfe00, DSPInterpreter::addis, &DSPEmitter::addis, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, false, false, false, false, true}, - {"CMPIS", 0x0600, 0xfe00, DSPInterpreter::cmpis, &DSPEmitter::cmpis, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, false, false, false, false, true}, - {"LRIS", 0x0800, 0xf800, DSPInterpreter::lris, &DSPEmitter::lris, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}}, false, false, false, false, true}, - - {"ADDI", 0x0200, 0xfeff, DSPInterpreter::addi, &DSPEmitter::addi, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"XORI", 0x0220, 0xfeff, DSPInterpreter::xori, &DSPEmitter::xori, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"ANDI", 0x0240, 0xfeff, DSPInterpreter::andi, &DSPEmitter::andi, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"ORI", 0x0260, 0xfeff, DSPInterpreter::ori, &DSPEmitter::ori, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"CMPI", 0x0280, 0xfeff, DSPInterpreter::cmpi, &DSPEmitter::cmpi, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - - {"ANDF", 0x02a0, 0xfeff, DSPInterpreter::andf, &DSPEmitter::andf, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - {"ANDCF", 0x02c0, 0xfeff, DSPInterpreter::andcf, &DSPEmitter::andcf, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, false, false, false, true, true}, - - {"ILRR", 0x0210, 0xfefc, DSPInterpreter::ilrr, &DSPEmitter::ilrr, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, - {"ILRRD", 0x0214, 0xfefc, DSPInterpreter::ilrrd, &DSPEmitter::ilrrd, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, - {"ILRRI", 0x0218, 0xfefc, DSPInterpreter::ilrri, &DSPEmitter::ilrri, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, - {"ILRRN", 0x021c, 0xfefc, DSPInterpreter::ilrrn, &DSPEmitter::ilrrn, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, - - // LOOPS - {"LOOP", 0x0040, 0xffe0, DSPInterpreter::loop, &DSPEmitter::loop, 1, 1, {{P_REG, 1, 0, 0, 0x001f}}, false, true, false, true, false}, - {"BLOOP", 0x0060, 0xffe0, DSPInterpreter::bloop, &DSPEmitter::bloop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - {"LOOPI", 0x1000, 0xff00, DSPInterpreter::loopi, &DSPEmitter::loopi, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}}, false, true, false, true, false}, - {"BLOOPI", 0x1100, 0xff00, DSPInterpreter::bloopi, &DSPEmitter::bloopi, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, - - // load and store value pointed by indexing reg and increment; LRR/SRR variants - {"LRR", 0x1800, 0xff80, DSPInterpreter::lrr, &DSPEmitter::lrr, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, false, false, false, false, false}, - {"LRRD", 0x1880, 0xff80, DSPInterpreter::lrrd, &DSPEmitter::lrrd, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, false, false, false, false, false}, - {"LRRI", 0x1900, 0xff80, DSPInterpreter::lrri, &DSPEmitter::lrri, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, false, false, false, false, false}, - {"LRRN", 0x1980, 0xff80, DSPInterpreter::lrrn, &DSPEmitter::lrrn, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, false, false, false, false, false}, - - {"SRR", 0x1a00, 0xff80, DSPInterpreter::srr, &DSPEmitter::srr, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, false, false, false, false, false}, - {"SRRD", 0x1a80, 0xff80, DSPInterpreter::srrd, &DSPEmitter::srrd, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, false, false, false, false, false}, - {"SRRI", 0x1b00, 0xff80, DSPInterpreter::srri, &DSPEmitter::srri, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, false, false, false, false, false}, - {"SRRN", 0x1b80, 0xff80, DSPInterpreter::srrn, &DSPEmitter::srrn, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, false, false, false, false, false}, - - //2 - {"LRS", 0x2000, 0xf800, DSPInterpreter::lrs, &DSPEmitter::lrs, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}}, false, false, false, false, false}, - {"SRS", 0x2800, 0xf800, DSPInterpreter::srs, &DSPEmitter::srs, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}}, false, false, false, false, false}, - -// opcodes that can be extended - - //3 - main opcode defined by 9 bits, extension defined by last 7 bits!! - {"XORR", 0x3000, 0xfc80, DSPInterpreter::xorr, &DSPEmitter::xorr, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"ANDR", 0x3400, 0xfc80, DSPInterpreter::andr, &DSPEmitter::andr, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"ORR", 0x3800, 0xfc80, DSPInterpreter::orr, &DSPEmitter::orr, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"ANDC", 0x3c00, 0xfe80, DSPInterpreter::andc, &DSPEmitter::andc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"ORC", 0x3e00, 0xfe80, DSPInterpreter::orc, &DSPEmitter::orc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"XORC", 0x3080, 0xfe80, DSPInterpreter::xorc, &DSPEmitter::xorc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"NOT", 0x3280, 0xfe80, DSPInterpreter::notc, &DSPEmitter::notc, 1, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"LSRNRX", 0x3480, 0xfc80, DSPInterpreter::lsrnrx, &DSPEmitter::lsrnrx, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"ASRNRX", 0x3880, 0xfc80, DSPInterpreter::asrnrx, &DSPEmitter::asrnrx, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"LSRNR", 0x3c80, 0xfe80, DSPInterpreter::lsrnr, &DSPEmitter::lsrnr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"ASRNR", 0x3e80, 0xfe80, DSPInterpreter::asrnr, &DSPEmitter::asrnr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - - //4 - {"ADDR", 0x4000, 0xf800, DSPInterpreter::addr, &DSPEmitter::addr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true, false, false, false, true}, - {"ADDAX", 0x4800, 0xfc00, DSPInterpreter::addax, &DSPEmitter::addax, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_AX, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"ADD", 0x4c00, 0xfe00, DSPInterpreter::add, &DSPEmitter::add, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"ADDP", 0x4e00, 0xfe00, DSPInterpreter::addp, &DSPEmitter::addp, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - - //5 - {"SUBR", 0x5000, 0xf800, DSPInterpreter::subr, &DSPEmitter::subr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true, false, false, false, true}, - {"SUBAX", 0x5800, 0xfc00, DSPInterpreter::subax, &DSPEmitter::subax, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_AX, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"SUB", 0x5c00, 0xfe00, DSPInterpreter::sub, &DSPEmitter::sub, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"SUBP", 0x5e00, 0xfe00, DSPInterpreter::subp, &DSPEmitter::subp, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - - //6 - {"MOVR", 0x6000, 0xf800, DSPInterpreter::movr, &DSPEmitter::movr, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true, false, false, false, true}, - {"MOVAX", 0x6800, 0xfc00, DSPInterpreter::movax, &DSPEmitter::movax, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_AX, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"MOV", 0x6c00, 0xfe00, DSPInterpreter::mov, &DSPEmitter::mov, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MOVP", 0x6e00, 0xfe00, DSPInterpreter::movp, &DSPEmitter::movp, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - - //7 - {"ADDAXL", 0x7000, 0xfc00, DSPInterpreter::addaxl, &DSPEmitter::addaxl, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true, false, false, false, true}, - {"INCM", 0x7400, 0xfe00, DSPInterpreter::incm, &DSPEmitter::incm, 1, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"INC", 0x7600, 0xfe00, DSPInterpreter::inc, &DSPEmitter::inc, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"DECM", 0x7800, 0xfe00, DSPInterpreter::decm, &DSPEmitter::decm, 1, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"DEC", 0x7a00, 0xfe00, DSPInterpreter::dec, &DSPEmitter::dec, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"NEG", 0x7c00, 0xfe00, DSPInterpreter::neg, &DSPEmitter::neg, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MOVNP", 0x7e00, 0xfe00, DSPInterpreter::movnp, &DSPEmitter::movnp, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - - //8 - {"NX", 0x8000, 0xf700, DSPInterpreter::nx, &DSPEmitter::nx, 1, 0, {}, true, false, false, false, false}, - {"CLR", 0x8100, 0xf700, DSPInterpreter::clr, &DSPEmitter::clr, 1, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - {"CMP", 0x8200, 0xff00, DSPInterpreter::cmp, &DSPEmitter::cmp, 1, 0, {}, true, false, false, false, true}, - {"MULAXH", 0x8300, 0xff00, DSPInterpreter::mulaxh, &DSPEmitter::mulaxh, 1, 0, {}, true, false, false, false, true}, - {"CLRP", 0x8400, 0xff00, DSPInterpreter::clrp, &DSPEmitter::clrp, 1, 0, {}, true, false, false, false, true}, - {"TSTPROD", 0x8500, 0xff00, DSPInterpreter::tstprod, &DSPEmitter::tstprod,1, 0, {}, true, false, false, false, true}, - {"TSTAXH", 0x8600, 0xfe00, DSPInterpreter::tstaxh, &DSPEmitter::tstaxh, 1, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"M2", 0x8a00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false, false, false}, - {"M0", 0x8b00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false, false, false}, - {"CLR15", 0x8c00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false, false, false}, - {"SET15", 0x8d00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false, false, false}, - {"SET16", 0x8e00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false, false, false}, - {"SET40", 0x8f00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false, false, false}, - - //9 - {"MUL", 0x9000, 0xf700, DSPInterpreter::mul, &DSPEmitter::mul, 1, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - {"ASR16", 0x9100, 0xf700, DSPInterpreter::asr16, &DSPEmitter::asr16, 1, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - {"MULMVZ", 0x9200, 0xf600, DSPInterpreter::mulmvz, &DSPEmitter::mulmvz, 1, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MULAC", 0x9400, 0xf600, DSPInterpreter::mulac, &DSPEmitter::mulac, 1, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MULMV", 0x9600, 0xf600, DSPInterpreter::mulmv, &DSPEmitter::mulmv, 1, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - - //a-b - {"MULX", 0xa000, 0xe700, DSPInterpreter::mulx, &DSPEmitter::mulx, 1, 2, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}}, true, false, false, false, true}, - {"ABS", 0xa100, 0xf700, DSPInterpreter::abs, &DSPEmitter::abs, 1, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - {"MULXMVZ", 0xa200, 0xe600, DSPInterpreter::mulxmvz, &DSPEmitter::mulxmvz,1, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MULXAC", 0xa400, 0xe600, DSPInterpreter::mulxac, &DSPEmitter::mulxac, 1, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MULXMV", 0xa600, 0xe600, DSPInterpreter::mulxmv, &DSPEmitter::mulxmv, 1, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"TST", 0xb100, 0xf700, DSPInterpreter::tst, &DSPEmitter::tst, 1, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - - //c-d - {"MULC", 0xc000, 0xe700, DSPInterpreter::mulc, &DSPEmitter::mulc, 1, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - {"CMPAR" , 0xc100, 0xe700, DSPInterpreter::cmpar, &DSPEmitter::cmpar, 1, 2, {{P_ACC, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - {"MULCMVZ", 0xc200, 0xe600, DSPInterpreter::mulcmvz, &DSPEmitter::mulcmvz,1, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MULCAC", 0xc400, 0xe600, DSPInterpreter::mulcac, &DSPEmitter::mulcac, 1, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MULCMV", 0xc600, 0xe600, DSPInterpreter::mulcmv, &DSPEmitter::mulcmv, 1, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - - //e - {"MADDX", 0xe000, 0xfc00, DSPInterpreter::maddx, &DSPEmitter::maddx, 1, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, - {"MSUBX", 0xe400, 0xfc00, DSPInterpreter::msubx, &DSPEmitter::msubx, 1, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, - {"MADDC", 0xe800, 0xfc00, DSPInterpreter::maddc, &DSPEmitter::maddc, 1, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, - {"MSUBC", 0xec00, 0xfc00, DSPInterpreter::msubc, &DSPEmitter::msubc, 1, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, true, false, false, false, true}, - - //f - {"LSL16", 0xf000, 0xfe00, DSPInterpreter::lsl16, &DSPEmitter::lsl16, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MADD", 0xf200, 0xfe00, DSPInterpreter::madd, &DSPEmitter::madd, 1, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"LSR16", 0xf400, 0xfe00, DSPInterpreter::lsr16, &DSPEmitter::lsr16, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"MSUB", 0xf600, 0xfe00, DSPInterpreter::msub, &DSPEmitter::msub, 1, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"ADDPAXZ", 0xf800, 0xfc00, DSPInterpreter::addpaxz, &DSPEmitter::addpaxz,1, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_AX, 1, 0, 8, 0x0100}}, true, false, false, false, true}, - {"CLRL", 0xfc00, 0xfe00, DSPInterpreter::clrl, &DSPEmitter::clrl, 1, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, true, false, false, false, true}, - {"MOVPZ", 0xfe00, 0xfe00, DSPInterpreter::movpz, &DSPEmitter::movpz, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, -}; - -const DSPOPCTemplate cw = - {"CW", 0x0000, 0x0000, NULL, NULL, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false, false}; - -// extended opcodes - -const DSPOPCTemplate opcodes_ext[] = -{ - {"XXX", 0x0000, 0x00fc, DSPInterpreter::Ext::nop, &DSPEmitter::nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, false, false, false}, - - {"DR", 0x0004, 0x00fc, DSPInterpreter::Ext::dr, &DSPEmitter::dr, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false, false}, - {"IR", 0x0008, 0x00fc, DSPInterpreter::Ext::ir, &DSPEmitter::ir, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false, false}, - {"NR", 0x000c, 0x00fc, DSPInterpreter::Ext::nr, &DSPEmitter::nr, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false, false}, - {"MV", 0x0010, 0x00f0, DSPInterpreter::Ext::mv, &DSPEmitter::mv, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}}, false, false, false}, - - {"S", 0x0020, 0x00e4, DSPInterpreter::Ext::s, &DSPEmitter::s, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, false, false, false}, - {"SN", 0x0024, 0x00e4, DSPInterpreter::Ext::sn, &DSPEmitter::sn, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, false, false, false}, - - {"L", 0x0040, 0x00c4, DSPInterpreter::Ext::l, &DSPEmitter::l, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false}, - {"LN", 0x0044, 0x00c4, DSPInterpreter::Ext::ln, &DSPEmitter::ln, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false}, - - {"LS", 0x0080, 0x00ce, DSPInterpreter::Ext::ls, &DSPEmitter::ls, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false, false}, - {"SL", 0x0082, 0x00ce, DSPInterpreter::Ext::sl, &DSPEmitter::sl, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false, false}, - {"LSN", 0x0084, 0x00ce, DSPInterpreter::Ext::lsn, &DSPEmitter::lsn, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false, false}, - {"SLN", 0x0086, 0x00ce, DSPInterpreter::Ext::sln, &DSPEmitter::sln, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false, false}, - {"LSM", 0x0088, 0x00ce, DSPInterpreter::Ext::lsm, &DSPEmitter::lsm, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false, false}, - {"SLM", 0x008a, 0x00ce, DSPInterpreter::Ext::slm, &DSPEmitter::slm, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false, false}, - {"LSNM", 0x008c, 0x00ce, DSPInterpreter::Ext::lsnm, &DSPEmitter::lsnm, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false, false}, - {"SLNM", 0x008e, 0x00ce, DSPInterpreter::Ext::slnm, &DSPEmitter::slnm, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false, false}, - - {"LD", 0x00c0, 0x00cc, DSPInterpreter::Ext::ld, &DSPEmitter::ld, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false}, - {"LDN", 0x00c4, 0x00cc, DSPInterpreter::Ext::ldn, &DSPEmitter::ldn, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false}, - {"LDM", 0x00c8, 0x00cc, DSPInterpreter::Ext::ldm, &DSPEmitter::ldm, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false}, - {"LDNM", 0x00cc, 0x00cc, DSPInterpreter::Ext::ldnm, &DSPEmitter::ldnm, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false}, -}; - -const int opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate); -const int opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate); - -const pdlabel_t pdlabels[] = -{ - {0xffa0, "COEF_A1_0", "COEF_A1_0",}, - {0xffa1, "COEF_A2_0", "COEF_A2_0",}, - {0xffa2, "COEF_A1_1", "COEF_A1_1",}, - {0xffa3, "COEF_A2_1", "COEF_A2_1",}, - {0xffa4, "COEF_A1_2", "COEF_A1_2",}, - {0xffa5, "COEF_A2_2", "COEF_A2_2",}, - {0xffa6, "COEF_A1_3", "COEF_A1_3",}, - {0xffa7, "COEF_A2_3", "COEF_A2_3",}, - {0xffa8, "COEF_A1_4", "COEF_A1_4",}, - {0xffa9, "COEF_A2_4", "COEF_A2_4",}, - {0xffaa, "COEF_A1_5", "COEF_A1_5",}, - {0xffab, "COEF_A2_5", "COEF_A2_5",}, - {0xffac, "COEF_A1_6", "COEF_A1_6",}, - {0xffad, "COEF_A2_6", "COEF_A2_6",}, - {0xffae, "COEF_A1_7", "COEF_A1_7",}, - {0xffaf, "COEF_A2_7", "COEF_A2_7",}, - - {0xffb0, "0xffb0", 0,}, - {0xffb1, "0xffb1", 0,}, - {0xffb2, "0xffb2", 0,}, - {0xffb3, "0xffb3", 0,}, - {0xffb4, "0xffb4", 0,}, - {0xffb5, "0xffb5", 0,}, - {0xffb6, "0xffb6", 0,}, - {0xffb7, "0xffb7", 0,}, - {0xffb8, "0xffb8", 0,}, - {0xffb9, "0xffb9", 0,}, - {0xffba, "0xffba", 0,}, - {0xffbb, "0xffbb", 0,}, - {0xffbc, "0xffbc", 0,}, - {0xffbd, "0xffbd", 0,}, - {0xffbe, "0xffbe", 0,}, - {0xffbf, "0xffbf", 0,}, - - {0xffc0, "0xffc0", 0,}, - {0xffc1, "0xffc1", 0,}, - {0xffc2, "0xffc2", 0,}, - {0xffc3, "0xffc3", 0,}, - {0xffc4, "0xffc4", 0,}, - {0xffc5, "0xffc5", 0,}, - {0xffc6, "0xffc6", 0,}, - {0xffc7, "0xffc7", 0,}, - {0xffc8, "0xffc8", 0,}, - {0xffc9, "DSCR", "DSP DMA Control Reg",}, - {0xffca, "0xffca", 0,}, - {0xffcb, "DSBL", "DSP DMA Block Length",}, - {0xffcc, "0xffcc", 0,}, - {0xffcd, "DSPA", "DSP DMA DMEM Address",}, - {0xffce, "DSMAH", "DSP DMA Mem Address H",}, - {0xffcf, "DSMAL", "DSP DMA Mem Address L",}, - - {0xffd0, "0xffd0",0,}, - {0xffd1, "SampleFormat", "SampleFormat",}, - {0xffd2, "0xffd2",0,}, - {0xffd3, "UnkZelda", "Unk Zelda reads/writes from/to it",}, - {0xffd4, "ACSAH", "Accelerator start address H",}, - {0xffd5, "ACSAL", "Accelerator start address L",}, - {0xffd6, "ACEAH", "Accelerator end address H",}, - {0xffd7, "ACEAL", "Accelerator end address L",}, - {0xffd8, "ACCAH", "Accelerator current address H",}, - {0xffd9, "ACCAL", "Accelerator current address L",}, - {0xffda, "pred_scale", "pred_scale",}, - {0xffdb, "yn1", "yn1",}, - {0xffdc, "yn2", "yn2",}, - {0xffdd, "ARAM", "Direct Read from ARAM (uses ADPCM)",}, - {0xffde, "GAIN", "Gain",}, - {0xffdf, "0xffdf", 0,}, - - {0xffe0, "0xffe0",0,}, - {0xffe1, "0xffe1",0,}, - {0xffe2, "0xffe2",0,}, - {0xffe3, "0xffe3",0,}, - {0xffe4, "0xffe4",0,}, - {0xffe5, "0xffe5",0,}, - {0xffe6, "0xffe6",0,}, - {0xffe7, "0xffe7",0,}, - {0xffe8, "0xffe8",0,}, - {0xffe9, "0xffe9",0,}, - {0xffea, "0xffea",0,}, - {0xffeb, "0xffeb",0,}, - {0xffec, "0xffec",0,}, - {0xffed, "0xffed",0,}, - {0xffee, "0xffee",0,}, - {0xffef, "AMDM", "ARAM DMA Request Mask",}, - - {0xfff0, "0xfff0",0,}, - {0xfff1, "0xfff1",0,}, - {0xfff2, "0xfff2",0,}, - {0xfff3, "0xfff3",0,}, - {0xfff4, "0xfff4",0,}, - {0xfff5, "0xfff5",0,}, - {0xfff6, "0xfff6",0,}, - {0xfff7, "0xfff7",0,}, - {0xfff8, "0xfff8",0,}, - {0xfff9, "0xfff9",0,}, - {0xfffa, "0xfffa",0,}, - {0xfffb, "DIRQ", "DSP IRQ Request",}, - {0xfffc, "DMBH", "DSP Mailbox H",}, - {0xfffd, "DMBL", "DSP Mailbox L",}, - {0xfffe, "CMBH", "CPU Mailbox H",}, - {0xffff, "CMBL", "CPU Mailbox L",}, -}; - -const u32 pdlabels_size = sizeof(pdlabels) / sizeof(pdlabel_t); - -const pdlabel_t regnames[] = -{ - {0x00, "AR0", "Addr Reg 00",}, - {0x01, "AR1", "Addr Reg 01",}, - {0x02, "AR2", "Addr Reg 02",}, - {0x03, "AR3", "Addr Reg 03",}, - {0x04, "IX0", "Index Reg 0",}, - {0x05, "IX1", "Index Reg 1",}, - {0x06, "IX2", "Index Reg 2",}, - {0x07, "IX3", "Index Reg 3",}, - {0x08, "WR0", "Wrapping Register 0",}, - {0x09, "WR1", "Wrapping Register 1",}, - {0x0a, "WR2", "Wrapping Register 2",}, - {0x0b, "WR3", "Wrapping Register 3",}, - {0x0c, "ST0", "Call stack",}, - {0x0d, "ST1", "Data stack",}, - {0x0e, "ST2", "Loop addr stack",}, - {0x0f, "ST3", "Loop counter",}, - {0x10, "AC0.H", "Accu High 0",}, - {0x11, "AC1.H", "Accu High 1",}, - {0x12, "CR", "Config Register",}, - {0x13, "SR", "Special Register",}, - {0x14, "PROD.L", "Prod L",}, - {0x15, "PROD.M1", "Prod M1",}, - {0x16, "PROD.H", "Prod H",}, - {0x17, "PROD.M2", "Prod M2",}, - {0x18, "AX0.L", "Extra Accu L 0",}, - {0x19, "AX1.L", "Extra Accu L 1",}, - {0x1a, "AX0.H", "Extra Accu H 0",}, - {0x1b, "AX1.H", "Extra Accu H 1",}, - {0x1c, "AC0.L", "Accu Low 0",}, - {0x1d, "AC1.L", "Accu Low 1",}, - {0x1e, "AC0.M", "Accu Mid 0",}, - {0x1f, "AC1.M", "Accu Mid 1",}, - - // To resolve combined register names. - {0x20, "ACC0", "Accu Full 0",}, - {0x21, "ACC1", "Accu Full 1",}, - {0x22, "AX0", "Extra Accu 0",}, - {0x23, "AX1", "Extra Accu 1",}, -}; - -const DSPOPCTemplate *opTable[OPTABLE_SIZE]; -const DSPOPCTemplate *extOpTable[EXT_OPTABLE_SIZE]; -u16 writeBackLog[WRITEBACKLOGSIZE]; -int writeBackLogIdx[WRITEBACKLOGSIZE]; - -const char* pdname(u16 val) -{ - static char tmpstr[12]; // nasty - - for (int i = 0; i < (int)(sizeof(pdlabels) / sizeof(pdlabel_t)); i++) - { - if (pdlabels[i].addr == val) - return pdlabels[i].name; - } - - sprintf(tmpstr, "0x%04x", val); - return tmpstr; -} - -const char *pdregname(int val) -{ - return regnames[val].name; -} - -const char *pdregnamelong(int val) -{ - return regnames[val].description; -} - -const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst) -{ - return opTable[inst]; -} - - -// This function could use the above GetOpTemplate, but then we'd lose the -// nice property that it catches colliding op masks. -void InitInstructionTable() -{ - // ext op table - for (int i = 0; i < EXT_OPTABLE_SIZE; i++) - extOpTable[i] = &cw; - - for (int i = 0; i < EXT_OPTABLE_SIZE; i++) - { - for (int j = 0; j < opcodes_ext_size; j++) - { - u16 mask = opcodes_ext[j].opcode_mask; - if ((mask & i) == opcodes_ext[j].opcode) - { - if (extOpTable[i] == &cw) - extOpTable[i] = &opcodes_ext[j]; - else - ERROR_LOG(DSPLLE, "opcode ext table place %d already in use for %s", i, opcodes_ext[j].name); - } - } - } - - // op table - for (int i = 0; i < OPTABLE_SIZE; i++) - opTable[i] = &cw; - - for (int i = 0; i < OPTABLE_SIZE; i++) - { - for (int j = 0; j < opcodes_size; j++) - { - u16 mask = opcodes[j].opcode_mask; - if ((mask & i) == opcodes[j].opcode) - { - if (opTable[i] == &cw) - opTable[i] = &opcodes[j]; - else - ERROR_LOG(DSPLLE, "opcode table place %d already in use for %s", i, opcodes[j].name); - } - } - } - - for (int i=0; i < WRITEBACKLOGSIZE; i++) - writeBackLogIdx[i] = -1; -} diff --git a/Source/Core/DSPCore/Src/DSPTables.h b/Source/Core/DSPCore/Src/DSPTables.h deleted file mode 100644 index 56ad885d23..0000000000 --- a/Source/Core/DSPCore/Src/DSPTables.h +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (C) 2003 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 - -//nclude "Common.h" -#include "DSPEmitter.h" -#include "DSPCommon.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_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_ACC_D = P_REG | 0x2080, - 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 OPTABLE_SIZE 0xffff + 1 -#define EXT_OPTABLE_SIZE 0xff + 1 - -typedef void (*dspIntFunc)(const UDSPInstruction); -typedef void (DSPEmitter::*dspJitFunc)(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; - - dspIntFunc intFunc; - dspJitFunc jitFunc; - - u8 size; - u8 param_count; - param2_t params[8]; - bool extended; - bool branch; - bool uncond_branch; - bool reads_pc; - bool updates_sr; -} 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 const DSPOPCTemplate cw; - -#define WRITEBACKLOGSIZE 5 - -extern const DSPOPCTemplate *opTable[OPTABLE_SIZE]; -extern const DSPOPCTemplate *extOpTable[EXT_OPTABLE_SIZE]; -extern u16 writeBackLog[WRITEBACKLOGSIZE]; -extern int writeBackLogIdx[WRITEBACKLOGSIZE]; - -// 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(); -void applyWriteBackLog(); -void zeroWriteBackLog(); -void zeroWriteBackLogPreserveAcc(u8 acc); - -const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst); - -inline void ExecuteInstruction(const UDSPInstruction inst) -{ - const DSPOPCTemplate *tinst = GetOpTemplate(inst); - - if (tinst->extended) { - if ((inst >> 12) == 0x3) - extOpTable[inst & 0x7F]->intFunc(inst); - else - extOpTable[inst & 0xFF]->intFunc(inst); - } - tinst->intFunc(inst); - if (tinst->extended) { - applyWriteBackLog(); - } -} - -#endif // _DSPTABLES_H diff --git a/Source/Core/DSPCore/Src/DspIntArithmetic.cpp b/Source/Core/DSPCore/Src/DspIntArithmetic.cpp deleted file mode 100644 index ba625395a1..0000000000 --- a/Source/Core/DSPCore/Src/DspIntArithmetic.cpp +++ /dev/null @@ -1,1152 +0,0 @@ -// Copyright (C) 2003 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 "DSPIntCCUtil.h" -#include "DSPIntUtil.h" - -// Arithmetic and accumulator control. - -namespace DSPInterpreter { - -// CLR $acR -// 1000 r001 xxxx xxxx -// Clears accumulator $acR -// -// flags out: --10 0100 -void clr(const UDSPInstruction opc) -{ - u8 reg = (opc >> 11) & 0x1; - - dsp_set_long_acc(reg, 0); - Update_SR_Register64(0); - zeroWriteBackLog(); -} - -// CLRL $acR.l -// 1111 110r xxxx xxxx -// Clears (and rounds!) $acR.l - low 16 bits of accumulator $acR. -// -// flags out: --xx xx00 -void clrl(const UDSPInstruction opc) -{ - u8 reg = (opc >> 8) & 0x1; - s64 acc = dsp_round_long_acc(dsp_get_long_acc(reg)); - - zeroWriteBackLog(); - - dsp_set_long_acc(reg, acc); - Update_SR_Register64(acc); -} - -//---- - -// ANDCF $acD.m, #I -// 0000 001r 1100 0000 -// iiii iiii iiii iiii -// Set logic zero (LZ) flag in status register $sr if result of logic AND of -// accumulator mid part $acD.m with immediate value I is equal I. -// -// flags out: -x-- ---- -void andcf(const UDSPInstruction opc) -{ - u8 reg = (opc >> 8) & 0x1; - - u16 imm = dsp_fetch_code(); - u16 val = dsp_get_acc_m(reg); - Update_SR_LZ(((val & imm) == imm) ? true : false); -} - -// ANDF $acD.m, #I -// 0000 001r 1010 0000 -// iiii iiii iiii iiii -// Set logic zero (LZ) flag in status register $sr if result of logical AND -// operation of accumulator mid part $acD.m with immediate value I is equal -// immediate value 0. -// -// flags out: -x-- ---- -void andf(const UDSPInstruction opc) -{ - u8 reg = (opc >> 8) & 0x1; - - u16 imm = dsp_fetch_code(); - u16 val = dsp_get_acc_m(reg); - Update_SR_LZ(((val & imm) == 0) ? true : false); -} - -//---- - -// TST -// 1011 r001 xxxx xxxx -// Test accumulator %acR. -// -// flags out: --xx xx00 -void tst(const UDSPInstruction opc) -{ - u8 reg = (opc >> 11) & 0x1; - - s64 acc = dsp_get_long_acc(reg); - Update_SR_Register64(acc); - zeroWriteBackLog(); -} - -// TSTAXH $axR.h -// 1000 011r xxxx xxxx -// Test high part of secondary accumulator $axR.h. -// -// flags out: --x0 xx00 -void tstaxh(const UDSPInstruction opc) -{ - u8 reg = (opc >> 8) & 0x1; - - s16 val = dsp_get_ax_h(reg); - Update_SR_Register16(val); - zeroWriteBackLog(); -} - -//---- - -// CMP -// 1000 0010 xxxx xxxx -// Compares accumulator $ac0 with accumulator $ac1. -// -// flags out: x-xx xxxx -void cmp(const UDSPInstruction opc) -{ - s64 acc0 = dsp_get_long_acc(0); - s64 acc1 = dsp_get_long_acc(1); - s64 res = dsp_convert_long_acc(acc0 - acc1); - - Update_SR_Register64(res, isCarry2(acc0, res), isOverflow(acc0, -acc1, res)); // CF -> influence on ABS/0xa100 - zeroWriteBackLog(); -} - -// CMPAR $acS axR.h -// 1100 0001 xxxx xxxx -// Compares accumulator $acS with accumulator axR.h. -// Not described by Duddie's doc - at least not as a separate instruction. -// -// flags out: x-xx xxxx -void cmpar(const UDSPInstruction opc) -{ - u8 rreg = ((opc >> 12) & 0x1) + DSP_REG_AXH0; - u8 sreg = (opc >> 11) & 0x1; - - s64 sr = dsp_get_long_acc(sreg); - s64 rr = (s16)g_dsp.r.ax[rreg-DSP_REG_AXH0].h; - rr <<= 16; - s64 res = dsp_convert_long_acc(sr - rr); - - Update_SR_Register64(res, isCarry2(sr, res), isOverflow(sr, -rr, res)); - zeroWriteBackLog(); -} - -// CMPI $amD, #I -// 0000 001r 1000 0000 -// iiii iiii iiii iiii -// Compares mid accumulator $acD.hm ($amD) with sign extended immediate value I. -// Although flags are being set regarding whole accumulator register. -// -// flags out: x-xx xxxx -void cmpi(const UDSPInstruction opc) -{ - u8 reg = (opc >> 8) & 0x1; - - s64 val = dsp_get_long_acc(reg); - s64 imm = (s64)(s16)dsp_fetch_code() << 16; // Immediate is considered to be at M level in the 40-bit accumulator. - s64 res = dsp_convert_long_acc(val - imm); - - Update_SR_Register64(res, isCarry2(val, res), isOverflow(val, -imm, res)); -} - -// CMPIS $acD, #I -// 0000 011d iiii iiii -// Compares accumulator with short immediate. Comaprison is executed -// by subtracting short immediate (8bit sign extended) from mid accumulator -// $acD.hm and computing flags based on whole accumulator $acD. -// -// flags out: x-xx xxxx -void cmpis(const UDSPInstruction opc) -{ - u8 areg = (opc >> 8) & 0x1; - - s64 acc = dsp_get_long_acc(areg); - s64 val = (s8)opc; - val <<= 16; - s64 res = dsp_convert_long_acc(acc - val); - - Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -val, res)); -} - -//---- - -// XORR $acD.m, $axS.h -// 0011 00sd 0xxx xxxx -// Logic XOR (exclusive or) middle part of accumulator $acD.m with -// high part of secondary accumulator $axS.h. -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void xorr(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - u16 accm = g_dsp.r.ac[dreg].m ^ g_dsp.r.ax[sreg].h; - - zeroWriteBackLogPreserveAcc(dreg); - - g_dsp.r.ac[dreg].m = accm; - Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -} - -// ANDR $acD.m, $axS.h -// 0011 01sd 0xxx xxxx -// Logic AND middle part of accumulator $acD.m with high part of -// secondary accumulator $axS.h. -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void andr(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - u16 accm = g_dsp.r.ac[dreg].m & g_dsp.r.ax[sreg].h; - - zeroWriteBackLogPreserveAcc(dreg); - - g_dsp.r.ac[dreg].m = accm; - Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -} - -// ORR $acD.m, $axS.h -// 0011 10sd 0xxx xxxx -// Logic OR middle part of accumulator $acD.m with high part of -// secondary accumulator $axS.h. -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void orr(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - u16 accm = g_dsp.r.ac[dreg].m | g_dsp.r.ax[sreg].h; - - zeroWriteBackLogPreserveAcc(dreg); - - g_dsp.r.ac[dreg].m = accm; - Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -} - -// ANDC $acD.m, $ac(1-D).m -// 0011 110d 0xxx xxxx -// Logic AND middle part of accumulator $acD.m with middle part of -// accumulator $ac(1-D).m -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void andc(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u16 accm = g_dsp.r.ac[dreg].m & g_dsp.r.ac[1 - dreg].m; - - zeroWriteBackLogPreserveAcc(dreg); - - g_dsp.r.ac[dreg].m = accm; - Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -} - -// ORC $acD.m, $ac(1-D).m -// 0011 111d 0xxx xxxx -// Logic OR middle part of accumulator $acD.m with middle part of -// accumulator $ac(1-D).m. -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void orc(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u16 accm = g_dsp.r.ac[dreg].m | g_dsp.r.ac[1 - dreg].m; - - zeroWriteBackLogPreserveAcc(dreg); - - g_dsp.r.ac[dreg].m = accm; - Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -} - -// XORC $acD.m -// 0011 000d 1xxx xxxx -// Logic XOR (exclusive or) middle part of accumulator $acD.m with $ac(1-D).m -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void xorc(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u16 accm = g_dsp.r.ac[dreg].m ^ g_dsp.r.ac[1 - dreg].m; - - zeroWriteBackLogPreserveAcc(dreg); - - g_dsp.r.ac[dreg].m = accm; - Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -} - -// NOT $acD.m -// 0011 001d 1xxx xxxx -// Invert all bits in dest reg, aka xor with 0xffff -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void notc(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u16 accm = g_dsp.r.ac[dreg].m ^ 0xffff; - - zeroWriteBackLogPreserveAcc(dreg); - - g_dsp.r.ac[dreg].m = accm; - Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); -} - -// XORI $acD.m, #I -// 0000 001r 0010 0000 -// iiii iiii iiii iiii -// Logic exclusive or (XOR) of accumulator mid part $acD.m with -// immediate value I. -// -// flags out: --xx xx00 -void xori(const UDSPInstruction opc) -{ - u8 reg = (opc >> 8) & 0x1; - u16 imm = dsp_fetch_code(); - g_dsp.r.ac[reg].m ^= imm; - - Update_SR_Register16((s16)g_dsp.r.ac[reg].m, false, false, isOverS32(dsp_get_long_acc(reg))); -} - -// ANDI $acD.m, #I -// 0000 001r 0100 0000 -// iiii iiii iiii iiii -// Logic AND of accumulator mid part $acD.m with immediate value I. -// -// flags out: --xx xx00 -void andi(const UDSPInstruction opc) -{ - u8 reg = (opc >> 8) & 0x1; - u16 imm = dsp_fetch_code(); - g_dsp.r.ac[reg].m &= imm; - - Update_SR_Register16((s16)g_dsp.r.ac[reg].m, false, false, isOverS32(dsp_get_long_acc(reg))); -} - -// ORI $acD.m, #I -// 0000 001r 0110 0000 -// iiii iiii iiii iiii -// Logic OR of accumulator mid part $acD.m with immediate value I. -// -// flags out: --xx xx00 -void ori(const UDSPInstruction opc) -{ - u8 reg = (opc >> 8) & 0x1; - u16 imm = dsp_fetch_code(); - g_dsp.r.ac[reg].m |= imm; - - Update_SR_Register16((s16)g_dsp.r.ac[reg].m, false, false, isOverS32(dsp_get_long_acc(reg))); -} - -//---- - -// ADDR $acD.M, $axS.L -// 0100 0ssd xxxx xxxx -// Adds register $axS.L to accumulator $acD.M register. -// -// flags out: x-xx xxxx -void addr(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0; - - s64 acc = dsp_get_long_acc(dreg); - s64 ax = 0; - switch(sreg) { - case DSP_REG_AXL0: - case DSP_REG_AXL1: - ax = (s16)g_dsp.r.ax[sreg-DSP_REG_AXL0].l; - break; - case DSP_REG_AXH0: - case DSP_REG_AXH1: - ax = (s16)g_dsp.r.ax[sreg-DSP_REG_AXH0].h; - break; - default: - ax = 0; - break; - } - ax <<= 16; - s64 res = acc + ax; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res)); -} - -// ADDAX $acD, $axS -// 0100 10sd xxxx xxxx -// Adds secondary accumulator $axS to accumulator register $acD. -// -// flags out: x-xx xxxx -void addax(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - s64 acc = dsp_get_long_acc(dreg); - s64 ax = dsp_get_long_acx(sreg); - s64 res = acc + ax; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res)); -} - -// ADD $acD, $ac(1-D) -// 0100 110d xxxx xxxx -// Adds accumulator $ac(1-D) to accumulator register $acD. -// -// flags out: x-xx xxxx -void add(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 acc0 = dsp_get_long_acc(dreg); - s64 acc1 = dsp_get_long_acc(1 - dreg); - s64 res = acc0 + acc1; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry(acc0, res), isOverflow(acc0, acc1, res)); -} - -// ADDP $acD -// 0100 111d xxxx xxxx -// Adds product register to accumulator register. -// -// flags out: x-xx xxxx -void addp(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 acc = dsp_get_long_acc(dreg); - s64 prod = dsp_get_long_prod(); - s64 res = acc + prod; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, prod, res)); -} - -// ADDAXL $acD, $axS.l -// 0111 00sd xxxx xxxx -// Adds secondary accumulator $axS.l to accumulator register $acD. -// should be unsigned values!! -// -// flags out: x-xx xxxx -void addaxl(const UDSPInstruction opc) -{ - u8 sreg = (opc >> 9) & 0x1; - u8 dreg = (opc >> 8) & 0x1; - - u64 acc = dsp_get_long_acc(dreg); - u16 acx = (u16)dsp_get_ax_l(sreg); - - u64 res = acc + acx; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, (s64)res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64((s64)res, isCarry(acc, res), isOverflow((s64)acc, (s64)acx, (s64)res)); -} - -// ADDI $amR, #I -// 0000 001r 0000 0000 -// iiii iiii iiii iiii -// Adds immediate (16-bit sign extended) to mid accumulator $acD.hm. -// -// flags out: x-xx xxxx -void addi(const UDSPInstruction opc) -{ - u8 areg = (opc >> 8) & 0x1; - - s64 acc = dsp_get_long_acc(areg); - s64 imm = (s16)dsp_fetch_code(); - imm <<= 16; - s64 res = acc + imm; - - dsp_set_long_acc(areg, res); - res = dsp_get_long_acc(areg); - Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res)); -} - -// ADDIS $acD, #I -// 0000 010d iiii iiii -// Adds short immediate (8-bit sign extended) to mid accumulator $acD.hm. -// -// flags out: x-xx xxxx -void addis(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 acc = dsp_get_long_acc(dreg); - s64 imm = (s8)(u8)opc; - imm <<= 16; - s64 res = acc + imm; - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res)); -} - -// INCM $acsD -// 0111 010d xxxx xxxx -// Increment 24-bit mid-accumulator $acsD. -// -// flags out: x-xx xxxx -void incm(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 sub = 0x10000; - s64 acc = dsp_get_long_acc(dreg); - s64 res = acc + sub; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, sub, res)); -} - -// INC $acD -// 0111 011d xxxx xxxx -// Increment accumulator $acD. -// -// flags out: x-xx xxxx -void inc(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 acc = dsp_get_long_acc(dreg); - s64 res = acc + 1; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, 1, res)); -} - -//---- - -// SUBR $acD.M, $axS.L -// 0101 0ssd xxxx xxxx -// Subtracts register $axS.L from accumulator $acD.M register. -// -// flags out: x-xx xxxx -void subr(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0; - - s64 acc = dsp_get_long_acc(dreg); - s64 ax = 0; - switch(sreg) { - case DSP_REG_AXL0: - case DSP_REG_AXL1: - ax = (s16)g_dsp.r.ax[sreg-DSP_REG_AXL0].l; - break; - case DSP_REG_AXH0: - case DSP_REG_AXH1: - ax = (s16)g_dsp.r.ax[sreg-DSP_REG_AXH0].h; - break; - default: - ax = 0; - break; - } - ax <<= 16; - s64 res = acc - ax; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -ax, res)); -} - -// SUBAX $acD, $axS -// 0101 10sd xxxx xxxx -// Subtracts secondary accumulator $axS from accumulator register $acD. -// -// flags out: x-xx xxxx -void subax(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - s64 acc = dsp_get_long_acc(dreg); - s64 acx = dsp_get_long_acx(sreg); - s64 res = acc - acx; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -acx, res)); -} - -// SUB $acD, $ac(1-D) -// 0101 110d xxxx xxxx -// Subtracts accumulator $ac(1-D) from accumulator register $acD. -// -// flags out: x-xx xxxx -void sub(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 acc1 = dsp_get_long_acc(dreg); - s64 acc2 = dsp_get_long_acc(1 - dreg); - s64 res = acc1 - acc2; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry2(acc1, res), isOverflow(acc1, -acc2, res)); -} - -// SUBP $acD -// 0101 111d xxxx xxxx -// Subtracts product register from accumulator register. -// -// flags out: x-xx xxxx -void subp(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 acc = dsp_get_long_acc(dreg); - s64 prod = dsp_get_long_prod(); - s64 res = acc - prod; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -prod, res)); -} - -// DECM $acsD -// 0111 100d xxxx xxxx -// Decrement 24-bit mid-accumulator $acsD. -// -// flags out: x-xx xxxx -void decm(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x01; - - s64 sub = 0x10000; - s64 acc = dsp_get_long_acc(dreg); - s64 res = acc - sub; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -sub, res)); -} - -// DEC $acD -// 0111 101d xxxx xxxx -// Decrement accumulator $acD. -// -// flags out: x-xx xxxx -void dec(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x01; - - s64 acc = dsp_get_long_acc(dreg); - s64 res = acc - 1; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -1, res)); -} - -//---- - -// NEG $acD -// 0111 110d xxxx xxxx -// Negate accumulator $acD. -// -// flags out: --xx xx00 -void neg(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 acc = dsp_get_long_acc(dreg); - acc = 0 - acc; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, acc); - Update_SR_Register64(dsp_get_long_acc(dreg)); -} - -// ABS $acD -// 1010 d001 xxxx xxxx -// absolute value of $acD -// -// flags out: --xx xx00 -void abs(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 11) & 0x1; - - s64 acc = dsp_get_long_acc(dreg); - - if (acc < 0) - acc = 0 - acc; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, acc); - Update_SR_Register64(dsp_get_long_acc(dreg)); -} -//---- - -// MOVR $acD, $axS.R -// 0110 0srd xxxx xxxx -// Moves register $axS.R (sign extended) to middle accumulator $acD.hm. -// Sets $acD.l to 0. -// TODO: Check what happens to acD.h. -// -// flags out: --xx xx00 -void movr(const UDSPInstruction opc) -{ - u8 areg = (opc >> 8) & 0x1; - u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0; - - s64 ax = 0; - switch(sreg) { - case DSP_REG_AXL0: - case DSP_REG_AXL1: - ax = (s16)g_dsp.r.ax[sreg-DSP_REG_AXL0].l; - break; - case DSP_REG_AXH0: - case DSP_REG_AXH1: - ax = (s16)g_dsp.r.ax[sreg-DSP_REG_AXH0].h; - break; - default: - ax = 0; - break; - } - ax <<= 16; - ax &= ~0xffff; - - zeroWriteBackLog(); - - dsp_set_long_acc(areg, ax); - Update_SR_Register64(ax); -} - -// MOVAX $acD, $axS -// 0110 10sd xxxx xxxx -// Moves secondary accumulator $axS to accumulator $axD. -// -// flags out: --xx xx00 -void movax(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - s64 acx = dsp_get_long_acx(sreg); - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, acx); - Update_SR_Register64(acx); -} - -// MOV $acD, $ac(1-D) -// 0110 110d xxxx xxxx -// Moves accumulator $ax(1-D) to accumulator $axD. -// -// flags out: --x0 xx00 -void mov(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u64 acc = dsp_get_long_acc(1 - dreg); - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, acc); - Update_SR_Register64(acc); -} - -//---- - -// LSL16 $acR -// 1111 000r xxxx xxxx -// Logically shifts left accumulator $acR by 16. -// -// flags out: --xx xx00 -void lsl16(const UDSPInstruction opc) -{ - u8 areg = (opc >> 8) & 0x1; - - s64 acc = dsp_get_long_acc(areg); - acc <<= 16; - - zeroWriteBackLog(); - - dsp_set_long_acc(areg, acc); - Update_SR_Register64(dsp_get_long_acc(areg)); -} - -// LSR16 $acR -// 1111 010r xxxx xxxx -// Logically shifts right accumulator $acR by 16. -// -// flags out: --xx xx00 -void lsr16(const UDSPInstruction opc) -{ - u8 areg = (opc >> 8) & 0x1; - - u64 acc = dsp_get_long_acc(areg); - acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes - acc >>= 16; - - zeroWriteBackLog(); - - dsp_set_long_acc(areg, (s64)acc); - Update_SR_Register64(dsp_get_long_acc(areg)); -} - -// ASR16 $acR -// 1001 r001 xxxx xxxx -// Arithmetically shifts right accumulator $acR by 16. -// -// flags out: --xx xx00 -void asr16(const UDSPInstruction opc) -{ - u8 areg = (opc >> 11) & 0x1; - - s64 acc = dsp_get_long_acc(areg); - acc >>= 16; - - zeroWriteBackLog(); - - dsp_set_long_acc(areg, acc); - Update_SR_Register64(dsp_get_long_acc(areg)); -} - -// LSL $acR, #I -// 0001 010r 00ii iiii -// Logically shifts left accumulator $acR by number specified by value I. -// -// flags out: --xx xx00 -void lsl(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x01; - u16 shift = opc & 0x3f; - u64 acc = dsp_get_long_acc(rreg); - - acc <<= shift; - - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -// LSR $acR, #I -// 0001 010r 01ii iiii -// Logically shifts right accumulator $acR by number specified by value -// calculated by negating sign extended bits 0-6. -// -// flags out: --xx xx00 -void lsr(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x01; - u16 shift; - u64 acc = dsp_get_long_acc(rreg); - acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes - - if ((opc & 0x3f) == 0) - shift = 0; - else - shift = 0x40 - (opc & 0x3f); - - acc >>= shift; - - dsp_set_long_acc(rreg, (s64)acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -// ASL $acR, #I -// 0001 010r 10ii iiii -// Logically shifts left accumulator $acR by number specified by value I. -// -// flags out: --xx xx00 -void asl(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x01; - u16 shift = opc & 0x3f; - u64 acc = dsp_get_long_acc(rreg); - - acc <<= shift; - - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -// ASR $acR, #I -// 0001 010r 11ii iiii -// Arithmetically shifts right accumulator $acR by number specified by -// value calculated by negating sign extended bits 0-6. -// -// flags out: --xx xx00 -void asr(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x01; - u16 shift; - - if ((opc & 0x3f) == 0) - shift = 0; - else - shift = 0x40 - (opc & 0x3f); - - // arithmetic shift - s64 acc = dsp_get_long_acc(dreg); - acc >>= shift; - - dsp_set_long_acc(dreg, acc); - Update_SR_Register64(dsp_get_long_acc(dreg)); -} - -// LSRN (fixed parameters) -// 0000 0010 1100 1010 -// Logically shifts right accumulator $ACC0 by lower 7-bit (signed) value in $AC1.M -// (if value negative, becomes left shift). -// -// flags out: --xx xx00 -void lsrn(const UDSPInstruction opc) -{ - s16 shift; - u16 accm = (u16)dsp_get_acc_m(1); - u64 acc = dsp_get_long_acc(0); - acc &= 0x000000FFFFFFFFFFULL; - - if ((accm & 0x3f) == 0) - shift = 0; - else if (accm & 0x40) - shift = -0x40 + (accm & 0x3f); - else - shift = accm & 0x3f; - - if (shift > 0) { - acc >>= shift; - } else if (shift < 0) { - acc <<= -shift; - } - - dsp_set_long_acc(0, (s64)acc); - Update_SR_Register64(dsp_get_long_acc(0)); -} - -// ASRN (fixed parameters) -// 0000 0010 1100 1011 -// Arithmetically shifts right accumulator $ACC0 by lower 7-bit (signed) value in $AC1.M -// (if value negative, becomes left shift). -// -// flags out: --xx xx00 -void asrn(const UDSPInstruction opc) -{ - s16 shift; - u16 accm = (u16)dsp_get_acc_m(1); - s64 acc = dsp_get_long_acc(0); - - if ((accm & 0x3f) == 0) - shift = 0; - else if (accm & 0x40) - shift = -0x40 + (accm & 0x3f); - else - shift = accm & 0x3f; - - if (shift > 0) { - acc >>= shift; - } else if (shift < 0) { - acc <<= -shift; - } - - dsp_set_long_acc(0, acc); - Update_SR_Register64(dsp_get_long_acc(0)); -} - -// LSRNRX $acD, $axS.h -// 0011 01sd 1xxx xxxx -// Logically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AX[S].H -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void lsrnrx(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - s16 shift; - u16 axh = g_dsp.r.ax[sreg].h; - u64 acc = dsp_get_long_acc(dreg); - acc &= 0x000000FFFFFFFFFFULL; - - if ((axh & 0x3f) == 0) - shift = 0; - else if (axh & 0x40) - shift = -0x40 + (axh & 0x3f); - else - shift = axh & 0x3f; - - if (shift > 0) { - acc <<= shift; - } else if (shift < 0) { - acc >>= -shift; - } - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, (s64)acc); - Update_SR_Register64(dsp_get_long_acc(dreg)); -} - -// ASRNRX $acD, $axS.h -// 0011 10sd 1xxx xxxx -// Arithmetically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AX[S].H -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void asrnrx(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - s16 shift; - u16 axh = g_dsp.r.ax[sreg].h; - s64 acc = dsp_get_long_acc(dreg); - - if ((axh & 0x3f) == 0) - shift = 0; - else if (axh & 0x40) - shift = -0x40 + (axh & 0x3f); - else - shift = axh & 0x3f; - - if (shift > 0) { - acc <<= shift; - } else if (shift < 0) { - acc >>= -shift; - } - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, acc); - Update_SR_Register64(dsp_get_long_acc(dreg)); -} - -// LSRNR $acD -// 0011 110d 1xxx xxxx -// Logically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void lsrnr(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s16 shift; - u16 accm = (u16)dsp_get_acc_m(1 - dreg); - u64 acc = dsp_get_long_acc(dreg); - acc &= 0x000000FFFFFFFFFFULL; - - if ((accm & 0x3f) == 0) - shift = 0; - else if (accm & 0x40) - shift = -0x40 + (accm & 0x3f); - else - shift = accm & 0x3f; - - if (shift > 0) - acc <<= shift; - else if (shift < 0) - acc >>= -shift; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, (s64)acc); - Update_SR_Register64(dsp_get_long_acc(dreg)); -} - -// ASRNR $acD -// 0011 111d 1xxx xxxx -// Arithmeticaly shift left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void asrnr(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s16 shift; - u16 accm = (u16)dsp_get_acc_m(1 - dreg); - s64 acc = dsp_get_long_acc(dreg); - - if ((accm & 0x3f) == 0) - shift = 0; - else if (accm & 0x40) - shift = -0x40 + (accm & 0x3f); - else - shift = accm & 0x3f; - - if (shift > 0) - acc <<= shift; - else if (shift < 0) - acc >>= -shift; - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, acc); - Update_SR_Register64(dsp_get_long_acc(dreg)); -} - - -} // namespace - diff --git a/Source/Core/DSPCore/Src/DspIntBranch.cpp b/Source/Core/DSPCore/Src/DspIntBranch.cpp deleted file mode 100644 index 1113425a87..0000000000 --- a/Source/Core/DSPCore/Src/DspIntBranch.cpp +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (C) 2003 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 & 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 & 0xf)) - { - u8 reg = (opc >> 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 & 0xf)) - { - // skip the next opcode - we have to lookup its size. - dsp_skip_inst(); - } -} - -// 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 & 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 & 0xf)) - { - u8 reg = (opc >> 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 & 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.sr = dsp_reg_load_stack(DSP_STACK_D); - g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C); - -} - -// 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 value from call stack $st0. Otherwise values from -// call stack $st0 and both loop stacks $st2 and $st3 are popped and execution -// continues at next opcode. -void HandleLoop() -{ - // Handle looping hardware. - const u16 rCallAddress = g_dsp.r.st[0]; - const u16 rLoopAddress = g_dsp.r.st[2]; - u16& rLoopCounter = g_dsp.r.st[3]; - - if (rLoopAddress > 0 && rLoopCounter > 0) - { - // FIXME: why -1? because we just read past it. - if (g_dsp.pc - 1 == rLoopAddress) - { - rLoopCounter--; - if (rLoopCounter > 0) - { - g_dsp.pc = rCallAddress; - } - else - { - // end of loop - dsp_reg_load_stack(0); - dsp_reg_load_stack(2); - dsp_reg_load_stack(3); - } - } - } -} - - -// 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 & 0x1f; - u16 cnt = dsp_op_read_reg(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 & 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 are allowed. -void bloop(const UDSPInstruction opc) -{ - u16 reg = opc & 0x1f; - u16 cnt = dsp_op_read_reg(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; - dsp_skip_inst(); - } -} - -// 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 are allowed. -void bloopi(const UDSPInstruction opc) -{ - u16 cnt = opc & 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; - dsp_skip_inst(); - } -} - -} // namespace diff --git a/Source/Core/DSPCore/Src/DspIntLoadStore.cpp b/Source/Core/DSPCore/Src/DspIntLoadStore.cpp deleted file mode 100644 index b43d6707b3..0000000000 --- a/Source/Core/DSPCore/Src/DspIntLoadStore.cpp +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (C) 2003 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 >> 8) & 0x7) + 0x18; - u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF); - dsp_dmem_write(addr, dsp_op_read_reg(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 >> 8) & 0x7) + 0x18; - u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF); - dsp_op_write_reg(reg, dsp_dmem_read(addr)); - dsp_conditional_extend_accum(reg); -} - -// 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 & 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 & 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; - 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 >> 5) & 0x3; - u8 dreg = opc & 0x1f; - - u16 val = dsp_dmem_read(dsp_op_read_reg(sreg)); - dsp_op_write_reg(dreg, val); - dsp_conditional_extend_accum(dreg); -} - -// 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 >> 5) & 0x3; - u8 dreg = opc & 0x1f; - - u16 val = dsp_dmem_read(dsp_op_read_reg(sreg)); - dsp_op_write_reg(dreg, val); - dsp_conditional_extend_accum(dreg); - g_dsp.r.ar[sreg] = 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 >> 5) & 0x3; - u8 dreg = opc & 0x1f; - - u16 val = dsp_dmem_read(dsp_op_read_reg(sreg)); - dsp_op_write_reg(dreg, val); - dsp_conditional_extend_accum(dreg); - g_dsp.r.ar[sreg] = 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 >> 5) & 0x3; - u8 dreg = opc & 0x1f; - - u16 val = dsp_dmem_read(dsp_op_read_reg(sreg)); - dsp_op_write_reg(dreg, val); - dsp_conditional_extend_accum(dreg); - g_dsp.r.ar[sreg] = dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[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 >> 5) & 0x3; - u8 sreg = opc & 0x1f; - - u16 val = dsp_op_read_reg(sreg); - dsp_dmem_write(g_dsp.r.ar[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 >> 5) & 0x3; - u8 sreg = opc & 0x1f; - - u16 val = dsp_op_read_reg(sreg); - dsp_dmem_write(g_dsp.r.ar[dreg], val); - g_dsp.r.ar[dreg] = 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 >> 5) & 0x3; - u8 sreg = opc & 0x1f; - - u16 val = dsp_op_read_reg(sreg); - dsp_dmem_write(g_dsp.r.ar[dreg], val); - g_dsp.r.ar[dreg] = 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 >> 5) & 0x3; - u8 sreg = opc & 0x1f; - - u16 val = dsp_op_read_reg(sreg); - dsp_dmem_write(g_dsp.r.ar[dreg], val); - g_dsp.r.ar[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[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 & 0x3; - u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1); - - g_dsp.r.ac[dreg-DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]); - dsp_conditional_extend_accum(dreg); -} - -// 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 & 0x3; - u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1); - - g_dsp.r.ac[dreg-DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]); - dsp_conditional_extend_accum(dreg); - g_dsp.r.ar[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 & 0x3; - u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1); - - g_dsp.r.ac[dreg-DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]); - dsp_conditional_extend_accum(dreg); - g_dsp.r.ar[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 & 0x3; - u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1); - - g_dsp.r.ac[dreg-DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]); - dsp_conditional_extend_accum(dreg); - g_dsp.r.ar[reg] = dsp_increase_addr_reg(reg, (s16)g_dsp.r.ix[reg]); -} - -} // namespace diff --git a/Source/Core/DSPCore/Src/DspIntMisc.cpp b/Source/Core/DSPCore/Src/DspIntMisc.cpp deleted file mode 100644 index f2c1f921af..0000000000 --- a/Source/Core/DSPCore/Src/DspIntMisc.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (C) 2003 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 { - -// MRR $D, $S -// 0001 11dd ddds ssss -// Move value from register $S to register $D. -// todo: Perform additional operation depending on destination register. -void mrr(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1f; - u8 dreg = (opc >> 5) & 0x1f; - - u16 val = dsp_op_read_reg(sreg); - dsp_op_write_reg(dreg, val); - dsp_conditional_extend_accum(dreg); -} - -// LRI $D, #I -// 0000 0000 100d dddd -// iiii iiii iiii iiii -// Load immediate value I to register $D. -// -// 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 & 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. -void lris(const UDSPInstruction opc) -{ - u8 reg = ((opc >> 8) & 0x7) + DSP_REG_AXL0; - u16 imm = (s8)opc; - dsp_op_write_reg(reg, imm); - dsp_conditional_extend_accum(reg); -} - -//---- - -// NX -// 1000 -000 xxxx xxxx -// No operation, but can be extended with extended opcode. -// 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. -void nx(const UDSPInstruction opc) -{ - zeroWriteBackLog(); -} - -//---- - -// DAR $arD -// 0000 0000 0000 01dd -// Decrement address register $arD. -void dar(const UDSPInstruction opc) -{ - g_dsp.r.ar[opc & 0x3] = dsp_decrement_addr_reg(opc & 0x3); -} - -// IAR $arD -// 0000 0000 0000 10dd -// Increment address register $arD. -void iar(const UDSPInstruction opc) -{ - g_dsp.r.ar[opc & 0x3] = dsp_increment_addr_reg(opc & 0x3); -} - -// SUBARN $arD -// 0000 0000 0000 11dd -// Subtract indexing register $ixD from an addressing register $arD. -// used only in IPL-NTSC ucode -void subarn(const UDSPInstruction opc) -{ - u8 dreg = opc & 0x3; - g_dsp.r.ar[dreg] = dsp_decrease_addr_reg(dreg, (s16)g_dsp.r.ix[dreg]); -} - -// ADDARN $arD, $ixS -// 0000 0000 0001 ssdd -// Adds indexing register $ixS to an addressing register $arD. -// It is critical for the Zelda ucode that this one wraps correctly. -void addarn(const UDSPInstruction opc) -{ - u8 dreg = opc & 0x3; - u8 sreg = (opc >> 2) & 0x3; - g_dsp.r.ar[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[sreg]); -} - -//---- - -// SBCLR #I -// 0001 0011 aaaa aiii -// bit of status register $sr. Bit number is calculated by adding 6 to -// immediate value I. -void sbclr(const UDSPInstruction opc) -{ - u8 bit = (opc & 0x7) + 6; - g_dsp.r.sr &= ~(1 << bit); -} - -// SBSET #I -// 0001 0010 aaaa aiii -// 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 & 0x7) + 6; - g_dsp.r.sr |= (1 << bit); -} - -// 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. -void srbith(const UDSPInstruction opc) -{ - zeroWriteBackLog(); - switch ((opc >> 8) & 0xf) - { - // M0/M2 change the multiplier mode (it can multiply by 2 for free). - case 0xa: // M2 - g_dsp.r.sr &= ~SR_MUL_MODIFY; - break; - case 0xb: // M0 - g_dsp.r.sr |= SR_MUL_MODIFY; - break; - - // If set, treat multiplicands as unsigned. - // If clear, treat them as signed. - case 0xc: // CLR15 - g_dsp.r.sr &= ~SR_MUL_UNSIGNED; - break; - case 0xd: // SET15 - g_dsp.r.sr |= SR_MUL_UNSIGNED; - break; - - // Automatic 40-bit sign extension when loading ACx.M. - // SET40 changes something very important: see the LRI instruction above. - case 0xe: // SET16 (CLR40) - g_dsp.r.sr &= ~SR_40_MODE_BIT; - break; - - case 0xf: // SET40 - g_dsp.r.sr |= SR_40_MODE_BIT; - break; - - default: - break; - } -} - -//---- - -void unknown(const UDSPInstruction opc) -{ - ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc, g_dsp.pc); -} - -} // namespace diff --git a/Source/Core/DSPCore/Src/DspIntMultiplier.cpp b/Source/Core/DSPCore/Src/DspIntMultiplier.cpp deleted file mode 100644 index fbde7a645c..0000000000 --- a/Source/Core/DSPCore/Src/DspIntMultiplier.cpp +++ /dev/null @@ -1,609 +0,0 @@ -// Copyright (C) 2003 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 - - -// Multiplier and product register control - -#include "DSPInterpreter.h" - -#include "DSPIntCCUtil.h" -#include "DSPIntUtil.h" - -namespace DSPInterpreter { - -// Only MULX family instructions have unsigned/mixed support. -inline s64 dsp_get_multiply_prod(u16 a, u16 b, u8 sign) -{ - s64 prod; - - if ((sign == 1) && (g_dsp.r.sr & SR_MUL_UNSIGNED)) //unsigned - prod = (u32)(a * b); - else if ((sign == 2) && (g_dsp.r.sr & SR_MUL_UNSIGNED)) //mixed - prod = a * (s16)b; - else - prod = (s16)a * (s16)b; //signed - - // Conditionally multiply by 2. - if ((g_dsp.r.sr & SR_MUL_MODIFY) == 0) - prod <<= 1; - - return prod; -} - -inline s64 dsp_multiply(u16 a, u16 b, u8 sign = 0) -{ - s64 prod = dsp_get_multiply_prod(a, b, sign); - return prod; -} - -inline s64 dsp_multiply_add(u16 a, u16 b, u8 sign = 0) -{ - s64 prod = dsp_get_long_prod() + dsp_get_multiply_prod(a, b, sign); - return prod; -} - -inline s64 dsp_multiply_sub(u16 a, u16 b, u8 sign = 0) -{ - s64 prod = dsp_get_long_prod() - dsp_get_multiply_prod(a, b, sign); - return prod; -} - -inline s64 dsp_multiply_mulx(u8 axh0, u8 axh1, u16 val1, u16 val2) -{ - s64 result; - - if ((axh0==0) && (axh1==0)) - result = dsp_multiply(val1, val2, 1); // unsigned support ON if both ax?.l regs are used - else if ((axh0==0) && (axh1==1)) - result = dsp_multiply(val1, val2, 2); // mixed support ON (u16)axl.0 * (s16)axh.1 - else if ((axh0==1) && (axh1==0)) - result = dsp_multiply(val2, val1, 2); // mixed support ON (u16)axl.1 * (s16)axh.0 - else - result = dsp_multiply(val1, val2, 0); // unsigned support OFF if both ax?.h regs are used - - return result; -} - -//---- - -// CLRP -// 1000 0100 xxxx xxxx -// Clears product register $prod. -// Magic numbers taken from duddie's doc -// -// 00ff_(fff0 + 0010)_0000 = 0100_0000_0000, conveniently, lower 40bits = 0 -// -// It's not ok, to just zero all of them, correct values should be set because of -// direct use of prod regs by AX/AXWII (look @that part of ucode). -void clrp(const UDSPInstruction opc) -{ - zeroWriteBackLog(); - - g_dsp.r.prod.l = 0x0000; - g_dsp.r.prod.m = 0xfff0; - g_dsp.r.prod.h = 0x00ff; - g_dsp.r.prod.m2 = 0x0010; -} - -// TSTPROD -// 1000 0101 xxxx xxxx -// Test prod regs value. -// -// flags out: --xx xx0x -void tstprod(const UDSPInstruction opc) -{ - s64 prod = dsp_get_long_prod(); - Update_SR_Register64(prod); - zeroWriteBackLog(); -} - -//---- - -// MOVP $acD -// 0110 111d xxxx xxxx -// Moves multiply product from $prod register to accumulator $acD register. -// -// flags out: --xx xx0x -void movp(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 acc = dsp_get_long_prod(); - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, acc); - Update_SR_Register64(acc); -} - -// MOVNP $acD -// 0111 111d xxxx xxxx -// Moves negative of multiply product from $prod register to accumulator -// $acD register. -// -// flags out: --xx xx0x -void movnp(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - - s64 acc = -dsp_get_long_prod(); - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, acc); - Update_SR_Register64(acc); -} - -// MOVPZ $acD -// 1111 111d xxxx xxxx -// Moves multiply product from $prod register to accumulator $acD -// register and sets (rounds) $acD.l to 0 -// -// flags out: --xx xx0x -void movpz(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x01; - - s64 acc = dsp_get_long_prod_round_prodl(); - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, acc); - Update_SR_Register64(acc); -} - -// ADDPAXZ $acD, $axS -// 1111 10sd xxxx xxxx -// Adds secondary accumulator $axS to product register and stores result -// in accumulator register. Low 16-bits of $acD ($acD.l) are set (round) to 0. -// -// TODO: ugly code and still small error here (+/- 1 in .m - randomly) -// flags out: --xx xx0x -void addpaxz(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - s64 oldprod = dsp_get_long_prod(); - s64 prod = dsp_get_long_prod_round_prodl(); - s64 ax = dsp_get_long_acx(sreg); - s64 res = prod + (ax & ~0xffff); - - zeroWriteBackLog(); - - dsp_set_long_acc(dreg, res); - res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry(oldprod, res), false); -} - -//---- - -// MULAXH -// 1000 0011 xxxx xxxx -// Multiply $ax0.h by $ax0.h -void mulaxh(const UDSPInstruction opc) -{ - s64 prod = dsp_multiply(dsp_get_ax_h(0), dsp_get_ax_h(0)); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -//---- - -// MUL $axS.l, $axS.h -// 1001 s000 xxxx xxxx -// Multiply low part $axS.l of secondary accumulator $axS by high part -// $axS.h of secondary accumulator $axS (treat them both as signed). -void mul(const UDSPInstruction opc) -{ - u8 sreg = (opc >> 11) & 0x1; - - u16 axl = dsp_get_ax_l(sreg); - u16 axh = dsp_get_ax_h(sreg); - s64 prod = dsp_multiply(axh, axl); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -// MULAC $axS.l, $axS.h, $acR -// 1001 s10r xxxx xxxx -// Add product register to accumulator register $acR. Multiply low part -// $axS.l of secondary accumulator $axS by high part $axS.h of secondary -// accumulator $axS (treat them both as signed). -// -// flags out: --xx xx0x -void mulac(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 11) & 0x1; - - s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod(); - u16 axl = dsp_get_ax_l(sreg); - u16 axh = dsp_get_ax_h(sreg); - s64 prod = dsp_multiply(axl, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -// MULMV $axS.l, $axS.h, $acR -// 1001 s11r xxxx xxxx -// Move product register to accumulator register $acR. Multiply low part -// $axS.l of secondary accumulator $axS by high part $axS.h of secondary -// accumulator $axS (treat them both as signed). -// -// flags out: --xx xx0x -void mulmv(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x1; - u8 sreg = ((opc >> 11) & 0x1); - - s64 acc = dsp_get_long_prod(); - u16 axl = dsp_get_ax_l(sreg); - u16 axh = dsp_get_ax_h(sreg); - s64 prod = dsp_multiply(axl, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -// MULMVZ $axS.l, $axS.h, $acR -// 1001 s01r xxxx xxxx -// Move product register to accumulator register $acR and clear (round) low part -// of accumulator register $acR.l. Multiply low part $axS.l of secondary -// accumulator $axS by high part $axS.h of secondary accumulator $axS (treat -// them both as signed). -// -// flags out: --xx xx0x -void mulmvz(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 11) & 0x1; - - s64 acc = dsp_get_long_prod_round_prodl(); - u16 axl = dsp_get_ax_l(sreg); - u16 axh = dsp_get_ax_h(sreg); - s64 prod = dsp_multiply(axl, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -//---- - -// MULX $ax0.S, $ax1.T -// 101s t000 xxxx xxxx -// Multiply one part $ax0 by one part $ax1. -// Part is selected by S and T bits. Zero selects low part, one selects high part. -void mulx(const UDSPInstruction opc) -{ - u8 treg = ((opc >> 11) & 0x1); - u8 sreg = ((opc >> 12) & 0x1); - - u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -// MULXAC $ax0.S, $ax1.T, $acR -// 101s t01r xxxx xxxx -// Add product register to accumulator register $acR. Multiply one part -// $ax0 by one part $ax1. Part is selected by S and -// T bits. Zero selects low part, one selects high part. -// -// flags out: --xx xx0x -void mulxac(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - - s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod(); - u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -// MULXMV $ax0.S, $ax1.T, $acR -// 101s t11r xxxx xxxx -// Move product register to accumulator register $acR. Multiply one part -// $ax0 by one part $ax1. Part is selected by S and -// T bits. Zero selects low part, one selects high part. -// -// flags out: --xx xx0x -void mulxmv(const UDSPInstruction opc) -{ - u8 rreg = ((opc >> 8) & 0x1); - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - - s64 acc = dsp_get_long_prod(); - u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -// MULXMVZ $ax0.S, $ax1.T, $acR -// 101s t01r xxxx xxxx -// Move product register to accumulator register $acR and clear (round) low part -// of accumulator register $acR.l. Multiply one part $ax0 by one part $ax1 -// Part is selected by S and T bits. Zero selects low part, -// one selects high part. -// -// flags out: --xx xx0x -void mulxmvz(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - - s64 acc = dsp_get_long_prod_round_prodl(); - u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -//---- - -// MULC $acS.m, $axT.h -// 110s t000 xxxx xxxx -// Multiply mid part of accumulator register $acS.m by high part $axS.h of -// secondary accumulator $axS (treat them both as signed). -void mulc(const UDSPInstruction opc) -{ - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - - u16 accm = dsp_get_acc_m(sreg); - u16 axh = dsp_get_ax_h(treg); - s64 prod = dsp_multiply(accm, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -// MULCAC $acS.m, $axT.h, $acR -// 110s t10r xxxx xxxx -// Multiply mid part of accumulator register $acS.m by high part $axS.h of -// secondary accumulator $axS (treat them both as signed). Add product -// register before multiplication to accumulator $acR. -// -// flags out: --xx xx0x -void mulcac(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - - s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod(); - u16 accm = dsp_get_acc_m(sreg); - u16 axh = dsp_get_ax_h(treg); - s64 prod = dsp_multiply(accm, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -// MULCMV $acS.m, $axT.h, $acR -// 110s t11r xxxx xxxx -// Multiply mid part of accumulator register $acS.m by high part $axT.h of -// secondary accumulator $axT (treat them both as signed). Move product -// register before multiplication to accumulator $acR. -// possible mistake in duddie's doc axT.h rather than axS.h -// -// flags out: --xx xx0x -void mulcmv(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - - s64 acc = dsp_get_long_prod(); - u16 accm = dsp_get_acc_m(sreg); - u16 axh = dsp_get_ax_h(treg); - s64 prod = dsp_multiply(accm, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -// MULCMVZ $acS.m, $axT.h, $acR -// 110s t01r xxxx xxxx -// (fixed possible bug in duddie's description, s->t) -// Multiply mid part of accumulator register $acS.m by high part $axT.h of -// secondary accumulator $axT (treat them both as signed). Move product -// register before multiplication to accumulator $acR, set (round) low part of -// accumulator $acR.l to zero. -// -// flags out: --xx xx0x -void mulcmvz(const UDSPInstruction opc) -{ - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - - s64 acc = dsp_get_long_prod_round_prodl(); - u16 accm = dsp_get_acc_m(sreg); - u16 axh = dsp_get_ax_h(treg); - s64 prod = dsp_multiply(accm, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); - dsp_set_long_acc(rreg, acc); - Update_SR_Register64(dsp_get_long_acc(rreg)); -} - -//---- - -// MADDX ax0.S ax1.T -// 1110 00st xxxx xxxx -// Multiply one part of secondary accumulator $ax0 (selected by S) by -// one part of secondary accumulator $ax1 (selected by T) (treat them both as -// signed) and add result to product register. -void maddx(const UDSPInstruction opc) -{ - u8 treg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - s64 prod = dsp_multiply_add(val1, val2); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -// MSUBX $(0x18+S*2), $(0x19+T*2) -// 1110 01st xxxx xxxx -// Multiply one part of secondary accumulator $ax0 (selected by S) by -// one part of secondary accumulator $ax1 (selected by T) (treat them both as -// signed) and subtract result from product register. -void msubx(const UDSPInstruction opc) -{ - u8 treg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - s64 prod = dsp_multiply_sub(val1, val2); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -// MADDC $acS.m, $axT.h -// 1110 10st xxxx xxxx -// Multiply middle part of accumulator $acS.m by high part of secondary -// accumulator $axT.h (treat them both as signed) and add result to product -// register. -void maddc(const UDSPInstruction opc) -{ - u8 treg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - u16 accm = dsp_get_acc_m(sreg); - u16 axh = dsp_get_ax_h(treg); - s64 prod = dsp_multiply_add(accm, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -// MSUBC $acS.m, $axT.h -// 1110 11st xxxx xxxx -// Multiply middle part of accumulator $acS.m by high part of secondary -// accumulator $axT.h (treat them both as signed) and subtract result from -// product register. -void msubc(const UDSPInstruction opc) -{ - u8 treg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - u16 accm = dsp_get_acc_m(sreg); - u16 axh = dsp_get_ax_h(treg); - s64 prod = dsp_multiply_sub(accm, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -// MADD $axS.l, $axS.h -// 1111 001s xxxx xxxx -// Multiply low part $axS.l of secondary accumulator $axS by high part -// $axS.h of secondary accumulator $axS (treat them both as signed) and add -// result to product register. -void madd(const UDSPInstruction opc) -{ - u8 sreg = (opc >> 8) & 0x1; - - u16 axl = dsp_get_ax_l(sreg); - u16 axh = dsp_get_ax_h(sreg); - s64 prod = dsp_multiply_add(axl, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -// MSUB $axS.l, $axS.h -// 1111 011s xxxx xxxx -// Multiply low part $axS.l of secondary accumulator $axS by high part -// $axS.h of secondary accumulator $axS (treat them both as signed) and -// subtract result from product register. -void msub(const UDSPInstruction opc) -{ - u8 sreg = (opc >> 8) & 0x1; - - u16 axl = dsp_get_ax_l(sreg); - u16 axh = dsp_get_ax_h(sreg); - s64 prod = dsp_multiply_sub(axl, axh); - - zeroWriteBackLog(); - - dsp_set_long_prod(prod); -} - -} // namespace diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp deleted file mode 100644 index fe396c6b97..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp +++ /dev/null @@ -1,1862 +0,0 @@ -// Copyright (C) 2003 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 "../DSPIntCCUtil.h" -#include "../DSPIntUtil.h" -#include "../DSPEmitter.h" -#include "../DSPAnalyzer.h" -#ifdef _M_X64 -#include "DSPJitUtil.h" -#endif -#include "x64Emitter.h" -#include "ABI.h" -using namespace Gen; - -// CLR $acR -// 1000 r001 xxxx xxxx -// Clears accumulator $acR -// -// flags out: --10 0100 -void DSPEmitter::clr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 reg = (opc >> 11) & 0x1; -// dsp_set_long_acc(reg, 0); - MOV(64, R(RAX), Imm64(0)); - set_long_acc(reg); -// Update_SR_Register64(0); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// CLRL $acR.l -// 1111 110r xxxx xxxx -// Clears (and rounds!) $acR.l - low 16 bits of accumulator $acR. -// -// flags out: --xx xx00 -void DSPEmitter::clrl(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 reg = (opc >> 8) & 0x1; -// s64 acc = dsp_round_long_acc(dsp_get_long_acc(reg)); - get_long_acc(reg); - round_long_acc(); -// dsp_set_long_acc(reg, acc); - set_long_acc(reg); -// Update_SR_Register64(acc); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -//---- - -// ANDCF $acD.m, #I -// 0000 001r 1100 0000 -// iiii iiii iiii iiii -// Set logic zero (LZ) flag in status register $sr if result of logic AND of -// accumulator mid part $acD.m with immediate value I is equal I. -// -// flags out: -x-- ---- -void DSPEmitter::andcf(const UDSPInstruction opc) -{ -#ifdef _M_X64 - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - u8 reg = (opc >> 8) & 0x1; -// u16 imm = dsp_fetch_code(); - u16 imm = dsp_imem_read(compilePC+1); -// u16 val = dsp_get_acc_m(reg); - get_acc_m(reg); -// Update_SR_LZ(((val & imm) == imm) ? true : false); -// if ((val & imm) == imm) -// g_dsp.r.sr |= SR_LOGIC_ZERO; -// else -// g_dsp.r.sr &= ~SR_LOGIC_ZERO; - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - AND(16, R(RAX), Imm16(imm)); - CMP(16, R(RAX), Imm16(imm)); - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - FixupBranch notLogicZero = J_CC(CC_NE); - OR(16, sr_reg, Imm16(SR_LOGIC_ZERO)); - FixupBranch exit = J(); - SetJumpTarget(notLogicZero); - AND(16, sr_reg, Imm16(~SR_LOGIC_ZERO)); - SetJumpTarget(exit); - gpr.putReg(DSP_REG_SR); - } -#else - Default(opc); -#endif -} - -// ANDF $acD.m, #I -// 0000 001r 1010 0000 -// iiii iiii iiii iiii -// Set logic zero (LZ) flag in status register $sr if result of logical AND -// operation of accumulator mid part $acD.m with immediate value I is equal -// immediate value 0. -// -// flags out: -x-- ---- -void DSPEmitter::andf(const UDSPInstruction opc) -{ -#ifdef _M_X64 - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - u8 reg = (opc >> 8) & 0x1; -// u16 imm = dsp_fetch_code(); - u16 imm = dsp_imem_read(compilePC+1); -// u16 val = dsp_get_acc_m(reg); - get_acc_m(reg); -// Update_SR_LZ(((val & imm) == 0) ? true : false); -// if ((val & imm) == 0) -// g_dsp.r.sr |= SR_LOGIC_ZERO; -// else -// g_dsp.r.sr &= ~SR_LOGIC_ZERO; - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - TEST(16, R(RAX), Imm16(imm)); - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - FixupBranch notLogicZero = J_CC(CC_NE); - OR(16, sr_reg, Imm16(SR_LOGIC_ZERO)); - FixupBranch exit = J(); - SetJumpTarget(notLogicZero); - AND(16, sr_reg, Imm16(~SR_LOGIC_ZERO)); - SetJumpTarget(exit); - gpr.putReg(DSP_REG_SR); - } -#else - Default(opc); -#endif -} - -//---- - -// TST -// 1011 r001 xxxx xxxx -// Test accumulator %acR. -// -// flags out: --xx xx00 -void DSPEmitter::tst(const UDSPInstruction opc) -{ -#ifdef _M_X64 - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - u8 reg = (opc >> 11) & 0x1; -// s64 acc = dsp_get_long_acc(reg); - get_long_acc(reg); -// Update_SR_Register64(acc); - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// TSTAXH $axR.h -// 1000 011r xxxx xxxx -// Test high part of secondary accumulator $axR.h. -// -// flags out: --x0 xx00 -void DSPEmitter::tstaxh(const UDSPInstruction opc) -{ -#ifdef _M_X64 - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - u8 reg = (opc >> 8) & 0x1; -// s16 val = dsp_get_ax_h(reg); - get_ax_h(reg); -// Update_SR_Register16(val); - Update_SR_Register16(); - } -#else - Default(opc); -#endif -} - -//---- - -// CMP -// 1000 0010 xxxx xxxx -// Compares accumulator $ac0 with accumulator $ac1. -// -// flags out: x-xx xxxx -void DSPEmitter::cmp(const UDSPInstruction opc) -{ -#ifdef _M_X64 - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { -// s64 acc0 = dsp_get_long_acc(0); - get_long_acc(0, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 acc1 = dsp_get_long_acc(1); - get_long_acc(1, RDX); -// s64 res = dsp_convert_long_acc(acc0 - acc1); - SUB(64, R(RAX), R(RDX)); -// Update_SR_Register64(res, isCarry2(acc0, res), isOverflow(acc0, -acc1, res)); // CF -> influence on ABS/0xa100 - NEG(64, R(RDX)); - Update_SR_Register64_Carry2(); - } -#else - Default(opc); -#endif -} - -// CMPAR $acS axR.h -// 1100 0001 xxxx xxxx -// Compares accumulator $acS with accumulator axR.h. -// Not described by Duddie's doc - at least not as a separate instruction. -// -// flags out: x-xx xxxx -void DSPEmitter::cmpar(const UDSPInstruction opc) -{ -#ifdef _M_X64 - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - u8 rreg = ((opc >> 12) & 0x1); - u8 sreg = (opc >> 11) & 0x1; - -// s64 sr = dsp_get_long_acc(sreg); - get_long_acc(sreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 rr = (s16)g_dsp.r.axh[rreg]; - get_ax_h(rreg, RDX); -// rr <<= 16; - SHL(64, R(RDX), Imm8(16)); -// s64 res = dsp_convert_long_acc(sr - rr); - SUB(64, R(RAX), R(RDX)); -// Update_SR_Register64(res, isCarry2(sr, res), isOverflow(sr, -rr, res)); - NEG(64, R(RDX)); - Update_SR_Register64_Carry2(); - } -#else - Default(opc); -#endif -} - -// CMPI $amD, #I -// 0000 001r 1000 0000 -// iiii iiii iiii iiii -// Compares mid accumulator $acD.hm ($amD) with sign extended immediate value I. -// Although flags are being set regarding whole accumulator register. -// -// flags out: x-xx xxxx -void DSPEmitter::cmpi(const UDSPInstruction opc) -{ -#ifdef _M_X64 - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - u8 reg = (opc >> 8) & 0x1; -// s64 val = dsp_get_long_acc(reg); - get_long_acc(reg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 imm = (s64)(s16)dsp_fetch_code() << 16; // Immediate is considered to be at M level in the 40-bit accumulator. - u16 imm = dsp_imem_read(compilePC+1); - MOV(64, R(RDX), Imm64((s64)(s16)imm << 16)); -// s64 res = dsp_convert_long_acc(val - imm); - SUB(64, R(RAX), R(RDX)); -// Update_SR_Register64(res, isCarry2(val, res), isOverflow(val, -imm, res)); - NEG(64, R(RDX)); - Update_SR_Register64_Carry2(); - } -#else - Default(opc); -#endif -} - -// CMPIS $acD, #I -// 0000 011d iiii iiii -// Compares accumulator with short immediate. Comaprison is executed -// by subtracting short immediate (8bit sign extended) from mid accumulator -// $acD.hm and computing flags based on whole accumulator $acD. -// -// flags out: x-xx xxxx -void DSPEmitter::cmpis(const UDSPInstruction opc) -{ -#ifdef _M_X64 - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - u8 areg = (opc >> 8) & 0x1; -// s64 acc = dsp_get_long_acc(areg); - get_long_acc(areg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 val = (s8)opc; -// val <<= 16; - MOV(64, R(RDX), Imm64((s64)(s8)opc << 16)); -// s64 res = dsp_convert_long_acc(acc - val); - SUB(64, R(RAX), R(RDX)); -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -val, res)); - NEG(64, R(RDX)); - Update_SR_Register64_Carry2(); - } -#else - Default(opc); -#endif -} - -//---- - -// XORR $acD.m, $axS.h -// 0011 00sd 0xxx xxxx -// Logic XOR (exclusive or) middle part of accumulator $acD.m with -// high part of secondary accumulator $axS.h. -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::xorr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; -// u16 accm = g_dsp.r.acm[dreg] ^ g_dsp.r.axh[sreg]; - get_acc_m(dreg, RAX); - get_ax_h(sreg, RDX); - XOR(64, R(RAX), R(RDX)); -// g_dsp.r.acm[dreg] = accm; - set_acc_m(dreg); -// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(dreg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -// ANDR $acD.m, $axS.h -// 0011 01sd 0xxx xxxx -// Logic AND middle part of accumulator $acD.m with high part of -// secondary accumulator $axS.h. -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::andr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - // u16 accm = g_dsp.r.acm[dreg] & g_dsp.r.axh[sreg]; - get_acc_m(dreg, RAX); - get_ax_h(sreg, RDX); - AND(64, R(RAX), R(RDX)); - // g_dsp.r.acm[dreg] = accm; - set_acc_m(dreg); - // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(dreg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -// ORR $acD.m, $axS.h -// 0011 10sd 0xxx xxxx -// Logic OR middle part of accumulator $acD.m with high part of -// secondary accumulator $axS.h. -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::orr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - // u16 accm = g_dsp.r.acm[dreg] | g_dsp.r.axh[sreg]; - get_acc_m(dreg, RAX); - get_ax_h(sreg, RDX); - OR(64, R(RAX), R(RDX)); - // g_dsp.r.acm[dreg] = accm; - set_acc_m(dreg); - // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(dreg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -// ANDC $acD.m, $ac(1-D).m -// 0011 110d 0xxx xxxx -// Logic AND middle part of accumulator $acD.m with middle part of -// accumulator $ac(1-D).m -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::andc(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; -// u16 accm = g_dsp.r.acm[dreg] & g_dsp.r.acm[1 - dreg]; - get_acc_m(dreg, RAX); - get_acc_m(1 - dreg, RDX); - AND(64, R(RAX), R(RDX)); - // g_dsp.r.acm[dreg] = accm; - set_acc_m(dreg); - // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(dreg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -// ORC $acD.m, $ac(1-D).m -// 0011 111d 0xxx xxxx -// Logic OR middle part of accumulator $acD.m with middle part of -// accumulator $ac(1-D).m. -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::orc(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - // u16 accm = g_dsp.r.acm[dreg] | g_dsp.r.acm[1 - dreg]; - get_acc_m(dreg, RAX); - get_acc_m(1 - dreg, RDX); - OR(64, R(RAX), R(RDX)); - // g_dsp.r.acm[dreg] = accm; - set_acc_m(dreg); - // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(dreg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -// XORC $acD.m -// 0011 000d 1xxx xxxx -// Logic XOR (exclusive or) middle part of accumulator $acD.m with $ac(1-D).m -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::xorc(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - // u16 accm = g_dsp.r.acm[dreg] ^ g_dsp.r.acm[1 - dreg]; - get_acc_m(dreg, RAX); - get_acc_m(1 - dreg, RDX); - XOR(64, R(RAX), R(RDX)); - // g_dsp.r.acm[dreg] = accm; - set_acc_m(dreg); - // Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(dreg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -// NOT $acD.m -// 0011 001d 1xxx xxxx -// Invert all bits in dest reg, aka xor with 0xffff -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::notc(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; -// u16 accm = g_dsp.r.acm[dreg] ^ 0xffff; - get_acc_m(dreg, RAX); - XOR(16, R(RAX), Imm16(0xffff)); -// g_dsp.r.acm[dreg] = accm; - set_acc_m(dreg); -// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(dreg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -// XORI $acD.m, #I -// 0000 001r 0010 0000 -// iiii iiii iiii iiii -// Logic exclusive or (XOR) of accumulator mid part $acD.m with -// immediate value I. -// -// flags out: --xx xx00 -void DSPEmitter::xori(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 reg = (opc >> 8) & 0x1; -// u16 imm = dsp_fetch_code(); - u16 imm = dsp_imem_read(compilePC+1); -// g_dsp.r.acm[reg] ^= imm; - get_acc_m(reg, RAX); - XOR(16, R(RAX), Imm16(imm)); - set_acc_m(reg); -// Update_SR_Register16((s16)g_dsp.r.acm[reg], false, false, isOverS32(dsp_get_long_acc(reg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(reg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -// ANDI $acD.m, #I -// 0000 001r 0100 0000 -// iiii iiii iiii iiii -// Logic AND of accumulator mid part $acD.m with immediate value I. -// -// flags out: --xx xx00 -void DSPEmitter::andi(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 reg = (opc >> 8) & 0x1; -// u16 imm = dsp_fetch_code(); - u16 imm = dsp_imem_read(compilePC+1); -// g_dsp.r.acm[reg] &= imm; - get_acc_m(reg, RAX); - AND(16, R(RAX), Imm16(imm)); - set_acc_m(reg); -// Update_SR_Register16((s16)g_dsp.r.acm[reg], false, false, isOverS32(dsp_get_long_acc(reg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(reg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -// ORI $acD.m, #I -// 0000 001r 0110 0000 -// iiii iiii iiii iiii -// Logic OR of accumulator mid part $acD.m with immediate value I. -// -// flags out: --xx xx00 -void DSPEmitter::ori(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 reg = (opc >> 8) & 0x1; - // u16 imm = dsp_fetch_code(); - u16 imm = dsp_imem_read(compilePC+1); - // g_dsp.r.acm[reg] |= imm; - get_acc_m(reg, RAX); - OR(16, R(RAX), Imm16(imm)); - set_acc_m(reg); - // Update_SR_Register16((s16)g_dsp.r.acm[reg], false, false, isOverS32(dsp_get_long_acc(reg))); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_acc(reg, RSI); - Update_SR_Register16_OverS32(); - } -#else - Default(opc); -#endif -} - -//---- - -// ADDR $acD.M, $axS.L -// 0100 0ssd xxxx xxxx -// Adds register $axS.L to accumulator $acD.M register. -// -// flags out: x-xx xxxx -void DSPEmitter::addr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0; - - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 ax = (s16)g_dsp.r[sreg]; - dsp_op_read_reg(sreg, RDX, SIGN); -// ax <<= 16; - SHL(64, R(RDX), Imm8(16)); -// s64 res = acc + ax; - ADD(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, res); -// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry(); - } - else - { - set_long_acc(dreg, RAX); - } - -#else - Default(opc); -#endif -} - -// ADDAX $acD, $axS -// 0100 10sd xxxx xxxx -// Adds secondary accumulator $axS to accumulator register $acD. -// -// flags out: x-xx xxxx -void DSPEmitter::addax(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 ax = dsp_get_long_acx(sreg); - get_long_acx(sreg, RDX); -// s64 res = acc + ax; - ADD(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// ADD $acD, $ac(1-D) -// 0100 110d xxxx xxxx -// Adds accumulator $ac(1-D) to accumulator register $acD. -// -// flags out: x-xx xxxx -void DSPEmitter::add(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - -// s64 acc0 = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 acc1 = dsp_get_long_acc(1 - dreg); - get_long_acc(1 - dreg, RDX); -// s64 res = acc0 + acc1; - ADD(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry(acc0, res), isOverflow(acc0, acc1, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// ADDP $acD -// 0100 111d xxxx xxxx -// Adds product register to accumulator register. -// -// flags out: x-xx xxxx -void DSPEmitter::addp(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 prod = dsp_get_long_prod(); - get_long_prod(RDX); -// s64 res = acc + prod; - ADD(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, prod, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry2(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// ADDAXL $acD, $axS.l -// 0111 00sd xxxx xxxx -// Adds secondary accumulator $axS.l to accumulator register $acD. -// should be unsigned values!! -// -// flags out: x-xx xxxx -void DSPEmitter::addaxl(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 sreg = (opc >> 9) & 0x1; - u8 dreg = (opc >> 8) & 0x1; - -// u64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// u16 acx = (u16)dsp_get_ax_l(sreg); - get_ax_l(sreg, RDX); -// u64 res = acc + acx; - ADD(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, (s64)res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64((s64)res, isCarry(acc, res), isOverflow((s64)acc, (s64)acx, (s64)res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// ADDI $amR, #I -// 0000 001r 0000 0000 -// iiii iiii iiii iiii -// Adds immediate (16-bit sign extended) to mid accumulator $acD.hm. -// -// flags out: x-xx xxxx -void DSPEmitter::addi(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 areg = (opc >> 8) & 0x1; -// s64 acc = dsp_get_long_acc(areg); - get_long_acc(areg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 imm = (s16)dsp_fetch_code(); - s16 imm = dsp_imem_read(compilePC+1); - //imm <<= 16; - MOV(16, R(RDX), Imm16(imm)); - MOVSX(64, 16, RDX, R(RDX)); - SHL(64, R(RDX), Imm8(16)); -// s64 res = acc + imm; - ADD(64, R(RAX), R(RDX)); -// dsp_set_long_acc(areg, res); -// res = dsp_get_long_acc(areg); -// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RSI), R(RAX)); - set_long_acc(areg, RSI); - Update_SR_Register64_Carry(); - } - else - { - set_long_acc(areg, RAX); - } -#else - Default(opc); -#endif -} - -// ADDIS $acD, #I -// 0000 010d iiii iiii -// Adds short immediate (8-bit sign extended) to mid accumulator $acD.hm. -// -// flags out: x-xx xxxx -void DSPEmitter::addis(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 imm = (s8)(u8)opc; -// imm <<= 16; - MOV(8, R(RDX), Imm8((u8)opc)); - MOVSX(64, 8, RDX, R(RDX)); - SHL(64, R(RDX), Imm8(16)); -// s64 res = acc + imm; - ADD(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// INCM $acsD -// 0111 010d xxxx xxxx -// Increment 24-bit mid-accumulator $acsD. -// -// flags out: x-xx xxxx -void DSPEmitter::incm(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - s64 subtract = 0x10000; -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 res = acc + sub; - ADD(64, R(RAX), Imm32((u32)subtract)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, subtract, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RDX), Imm32((u32)subtract)); - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry(); - } - else - { - set_long_acc(dreg); - Update_SR_Register64_Carry(); - } -#else - Default(opc); -#endif -} - -// INC $acD -// 0111 011d xxxx xxxx -// Increment accumulator $acD. -// -// flags out: x-xx xxxx -void DSPEmitter::inc(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 res = acc + 1; - ADD(64, R(RAX), Imm8(1)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, 1, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RDX), Imm64(1)); - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry(); - } - else - { - set_long_acc(dreg); - Update_SR_Register64_Carry(); - } -#else - Default(opc); -#endif -} - -//---- - -// SUBR $acD.M, $axS.L -// 0101 0ssd xxxx xxxx -// Subtracts register $axS.L from accumulator $acD.M register. -// -// flags out: x-xx xxxx -void DSPEmitter::subr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0; - -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 ax = (s16)g_dsp.r[sreg]; - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - dsp_op_read_reg(sreg, RDX, SIGN); -// ax <<= 16; - SHL(64, R(RDX), Imm8(16)); -// s64 res = acc - ax; - SUB(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -ax, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - NEG(64, R(RDX)); - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry2(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// SUBAX $acD, $axS -// 0101 10sd xxxx xxxx -// Subtracts secondary accumulator $axS from accumulator register $acD. -// -// flags out: x-xx xxxx -void DSPEmitter::subax(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 acx = dsp_get_long_acx(sreg); - get_long_acx(sreg, RDX); -// s64 res = acc - acx; - SUB(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -acx, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - NEG(64, R(RDX)); - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry2(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// SUB $acD, $ac(1-D) -// 0101 110d xxxx xxxx -// Subtracts accumulator $ac(1-D) from accumulator register $acD. -// -// flags out: x-xx xxxx -void DSPEmitter::sub(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; -// s64 acc1 = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 acc2 = dsp_get_long_acc(1 - dreg); - get_long_acc(1 - dreg, RDX); -// s64 res = acc1 - acc2; - SUB(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry2(acc1, res), isOverflow(acc1, -acc2, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - NEG(64, R(RDX)); - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry2(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// SUBP $acD -// 0101 111d xxxx xxxx -// Subtracts product register from accumulator register. -// -// flags out: x-xx xxxx -void DSPEmitter::subp(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 prod = dsp_get_long_prod(); - get_long_prod(RDX); -// s64 res = acc - prod; - SUB(64, R(RAX), R(RDX)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -prod, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - NEG(64, R(RDX)); - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry2(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// DECM $acsD -// 0111 100d xxxx xxxx -// Decrement 24-bit mid-accumulator $acsD. -// -// flags out: x-xx xxxx -void DSPEmitter::decm(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x01; - s64 subtract = 0x10000; -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 res = acc - sub; - SUB(64, R(RAX), Imm32((u32)subtract)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -subtract, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RDX), Imm64(-subtract)); - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry2(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -// DEC $acD -// 0111 101d xxxx xxxx -// Decrement accumulator $acD. -// -// flags out: x-xx xxxx -void DSPEmitter::dec(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x01; -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RCX); - MOV(64, R(RAX), R(RCX)); -// s64 res = acc - 1; - SUB(64, R(RAX), Imm32(1)); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -1, res)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - MOV(64, R(RDX), Imm64(-1)); - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry2(); - } - else - { - set_long_acc(dreg); - } -#else - Default(opc); -#endif -} - -//---- - -// NEG $acD -// 0111 110d xxxx xxxx -// Negate accumulator $acD. -// -// flags out: --xx xx00 -void DSPEmitter::neg(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg); -// acc = 0 - acc; - NEG(64, R(RAX)); -// dsp_set_long_acc(dreg, acc); - set_long_acc(dreg); -// Update_SR_Register64(dsp_get_long_acc(dreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// ABS $acD -// 1010 d001 xxxx xxxx -// absolute value of $acD -// -// flags out: --xx xx00 -void DSPEmitter::abs(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 11) & 0x1; - -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg); -// if (acc < 0) acc = 0 - acc; - CMP(64, R(RAX), Imm8(0)); - FixupBranch lessThan = J_CC(CC_L); - NEG(64, R(RAX)); - set_long_acc(dreg); - SetJumpTarget(lessThan); -// dsp_set_long_acc(dreg, acc); - set_long_acc(dreg); -// Update_SR_Register64(dsp_get_long_acc(dreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} -//---- - -// MOVR $acD, $axS.R -// 0110 0srd xxxx xxxx -// Moves register $axS.R (sign extended) to middle accumulator $acD.hm. -// Sets $acD.l to 0. -// TODO: Check what happens to acD.h. -// -// flags out: --xx xx00 -void DSPEmitter::movr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 areg = (opc >> 8) & 0x1; - u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0; - -// s64 acc = (s16)g_dsp.r[sreg]; - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - dsp_op_read_reg(sreg, RAX, SIGN); -// acc <<= 16; - SHL(64, R(RAX), Imm8(16)); -// acc &= ~0xffff; -// dsp_set_long_acc(areg, acc); - set_long_acc(areg); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// MOVAX $acD, $axS -// 0110 10sd xxxx xxxx -// Moves secondary accumulator $axS to accumulator $axD. -// -// flags out: --xx xx00 -void DSPEmitter::movax(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - -// s64 acx = dsp_get_long_acx(sreg); - get_long_acx(sreg); -// dsp_set_long_acc(dreg, acx); - set_long_acc(dreg); -// Update_SR_Register64(acx); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// MOV $acD, $ac(1-D) -// 0110 110d xxxx xxxx -// Moves accumulator $ax(1-D) to accumulator $axD. -// -// flags out: --x0 xx00 -void DSPEmitter::mov(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; -// u64 acc = dsp_get_long_acc(1 - dreg); - get_long_acc(1 - dreg); -// dsp_set_long_acc(dreg, acc); - set_long_acc(dreg); -// Update_SR_Register64(acc); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -//---- - -// LSL16 $acR -// 1111 000r xxxx xxxx -// Logically shifts left accumulator $acR by 16. -// -// flags out: --xx xx00 -void DSPEmitter::lsl16(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 areg = (opc >> 8) & 0x1; -// s64 acc = dsp_get_long_acc(areg); - get_long_acc(areg); -// acc <<= 16; - SHL(64, R(RAX), Imm8(16)); -// dsp_set_long_acc(areg, acc); - set_long_acc(areg); -// Update_SR_Register64(dsp_get_long_acc(areg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// LSR16 $acR -// 1111 010r xxxx xxxx -// Logically shifts right accumulator $acR by 16. -// -// flags out: --xx xx00 -void DSPEmitter::lsr16(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 areg = (opc >> 8) & 0x1; - -// u64 acc = dsp_get_long_acc(areg); - get_long_acc(areg); -// acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes -// acc >>= 16; - SHR(64, R(RAX), Imm8(16)); - AND(64, R(RAX), Imm32(0xffffff)); -// dsp_set_long_acc(areg, (s64)acc); - set_long_acc(areg); -// Update_SR_Register64(dsp_get_long_acc(areg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// ASR16 $acR -// 1001 r001 xxxx xxxx -// Arithmetically shifts right accumulator $acR by 16. -// -// flags out: --xx xx00 -void DSPEmitter::asr16(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 areg = (opc >> 11) & 0x1; - -// s64 acc = dsp_get_long_acc(areg); - get_long_acc(areg); -// acc >>= 16; - SHR(64, R(RAX), Imm8(16)); -// dsp_set_long_acc(areg, acc); - set_long_acc(areg); -// Update_SR_Register64(dsp_get_long_acc(areg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// LSL $acR, #I -// 0001 010r 00ii iiii -// Logically shifts left accumulator $acR by number specified by value I. -// -// flags out: --xx xx00 -void DSPEmitter::lsl(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x01; - u16 shift = opc & 0x3f; -// u64 acc = dsp_get_long_acc(rreg); - get_long_acc(rreg); - -// acc <<= shift; - SHL(64, R(RAX), Imm8((u8)shift)); - -// dsp_set_long_acc(rreg, acc); - set_long_acc(rreg); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// LSR $acR, #I -// 0001 010r 01ii iiii -// Logically shifts right accumulator $acR by number specified by value -// calculated by negating sign extended bits 0-6. -// -// flags out: --xx xx00 -void DSPEmitter::lsr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x01; - u16 shift; -// u64 acc = dsp_get_long_acc(rreg); - get_long_acc(rreg); - - if ((opc & 0x3f) == 0) - shift = 0; - else - shift = 0x40 - (opc & 0x3f); - - if (shift) - { - // acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes - SHL(64, R(RAX), Imm8(24)); - // acc >>= shift; - SHR(64, R(RAX), Imm8(shift + 24)); - } - -// dsp_set_long_acc(rreg, (s64)acc); - set_long_acc(rreg); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// ASL $acR, #I -// 0001 010r 10ii iiii -// Logically shifts left accumulator $acR by number specified by value I. -// -// flags out: --xx xx00 -void DSPEmitter::asl(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x01; - u16 shift = opc & 0x3f; -// u64 acc = dsp_get_long_acc(rreg); - get_long_acc(rreg); -// acc <<= shift; - SHL(64, R(RAX), Imm8((u8)shift)); -// dsp_set_long_acc(rreg, acc); - set_long_acc(rreg); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// ASR $acR, #I -// 0001 010r 11ii iiii -// Arithmetically shifts right accumulator $acR by number specified by -// value calculated by negating sign extended bits 0-6. -// -// flags out: --xx xx00 -void DSPEmitter::asr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x01; - u16 shift; - - if ((opc & 0x3f) == 0) - shift = 0; - else - shift = 0x40 - (opc & 0x3f); - - // arithmetic shift -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg); -// acc >>= shift; - SHR(64, R(RAX), Imm8((u8)shift)); - -// dsp_set_long_acc(dreg, acc); - set_long_acc(dreg); -// Update_SR_Register64(dsp_get_long_acc(dreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// LSRN (fixed parameters) -// 0000 0010 1100 1010 -// Logically shifts right accumulator $ACC0 by lower 7-bit (signed) value in $AC1.M -// (if value negative, becomes left shift). -// -// flags out: --xx xx00 -void DSPEmitter::lsrn(const UDSPInstruction opc) -{ -#ifdef _M_X64 -// s16 shift; -// u16 accm = (u16)dsp_get_acc_m(1); - get_acc_m(1); -// u64 acc = dsp_get_long_acc(0); - get_long_acc(0, RDX); -// acc &= 0x000000FFFFFFFFFFULL; - SHL(64, R(RDX), Imm8(24)); - SHR(64, R(RDX), Imm8(24)); - - // if ((accm & 0x3f) == 0) - // shift = 0; - // else if (accm & 0x40) - // shift = -0x40 + (accm & 0x3f); - // else - // shift = accm & 0x3f; - - // if (shift > 0) { - // acc >>= shift; - // } else if (shift < 0) { - // acc <<= -shift; - // } - - CMP(64, R(RDX), Imm8(0)); - FixupBranch zero = J_CC(CC_E); - TEST(16, R(RAX), Imm16(0x3f)); - FixupBranch noShift = J_CC(CC_Z); - MOVZX(64, 16, RCX, R(RAX)); - AND(16, R(RCX), Imm16(0x3f)); - TEST(16, R(RAX), Imm16(0x40)); - FixupBranch shiftLeft = J_CC(CC_Z); - NEG(16, R(RCX)); - ADD(16, R(RCX), Imm16(0x40)); - SHL(64, R(RDX), R(RCX)); - FixupBranch exit = J(); - SetJumpTarget(shiftLeft); - SAR(64, R(RDX), R(RCX)); - SetJumpTarget(noShift); - SetJumpTarget(exit); - -// dsp_set_long_acc(0, (s64)acc); - set_long_acc(0, RDX); - SetJumpTarget(zero); -// Update_SR_Register64(dsp_get_long_acc(0)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RDX); - } -#else - Default(opc); -#endif -} - -// ASRN (fixed parameters) -// 0000 0010 1100 1011 -// Arithmetically shifts right accumulator $ACC0 by lower 7-bit (signed) value in $AC1.M -// (if value negative, becomes left shift). -// -// flags out: --xx xx00 -void DSPEmitter::asrn(const UDSPInstruction opc) -{ -#ifdef _M_X64 -// s16 shift; -// u16 accm = (u16)dsp_get_acc_m(1); - get_acc_m(1); -// s64 acc = dsp_get_long_acc(0); - get_long_acc(0, RDX); - -// if ((accm & 0x3f) == 0) -// shift = 0; -// else if (accm & 0x40) -// shift = -0x40 + (accm & 0x3f); -// else -// shift = accm & 0x3f; - -// if (shift > 0) { -// acc >>= shift; -// } else if (shift < 0) { -// acc <<= -shift; -// } - - CMP(64, R(RDX), Imm8(0)); - FixupBranch zero = J_CC(CC_E); - TEST(16, R(RAX), Imm16(0x3f)); - FixupBranch noShift = J_CC(CC_Z); - MOVZX(64, 16, RCX, R(RAX)); - AND(16, R(RCX), Imm16(0x3f)); - TEST(16, R(RAX), Imm16(0x40)); - FixupBranch shiftLeft = J_CC(CC_Z); - NEG(16, R(RCX)); - ADD(16, R(RCX), Imm16(0x40)); - SHL(64, R(RDX), R(RCX)); - FixupBranch exit = J(); - SetJumpTarget(shiftLeft); - SAR(64, R(RDX), R(RCX)); - SetJumpTarget(noShift); - SetJumpTarget(exit); - -// dsp_set_long_acc(0, acc); -// Update_SR_Register64(dsp_get_long_acc(0)); - set_long_acc(0, RDX); - SetJumpTarget(zero); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RDX); - } -#else - Default(opc); -#endif -} - -// LSRNRX $acD, $axS.h -// 0011 01sd 1xxx xxxx -// Logically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AX[S].H -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::lsrnrx(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - -// s16 shift; -// u16 axh = g_dsp.r.axh[sreg]; - get_ax_h(sreg); -// u64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RDX); -// acc &= 0x000000FFFFFFFFFFULL; - SHL(64, R(RDX), Imm8(24)); - SHR(64, R(RDX), Imm8(24)); - -// if ((axh & 0x3f) == 0) -// shift = 0; -// else if (axh & 0x40) -// shift = -0x40 + (axh & 0x3f); -// else -// shift = axh & 0x3f; - -// if (shift > 0) { -// acc <<= shift; -// } else if (shift < 0) { -// acc >>= -shift; -// } - - CMP(64, R(RDX), Imm8(0)); - FixupBranch zero = J_CC(CC_E); - TEST(16, R(RAX), Imm16(0x3f)); - FixupBranch noShift = J_CC(CC_Z); - MOVZX(64, 16, RCX, R(RAX)); - AND(16, R(RCX), Imm16(0x3f)); - TEST(16, R(RAX), Imm16(0x40)); - FixupBranch shiftLeft = J_CC(CC_Z); - NEG(16, R(RCX)); - ADD(16, R(RCX), Imm16(0x40)); - SAR(64, R(RDX), R(RCX)); - FixupBranch exit = J(); - SetJumpTarget(shiftLeft); - SHL(64, R(RDX), R(RCX)); - SetJumpTarget(noShift); - SetJumpTarget(exit); - -// dsp_set_long_acc(dreg, (s64)acc); -// Update_SR_Register64(dsp_get_long_acc(dreg)); - set_long_acc(dreg, RDX); - SetJumpTarget(zero); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RDX); - } -#else - Default(opc); -#endif -} - -// ASRNRX $acD, $axS.h -// 0011 10sd 1xxx xxxx -// Arithmetically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AX[S].H -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::asrnrx(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - -// s16 shift; -// u16 axh = g_dsp.r.axh[sreg]; - get_ax_h(sreg); -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RDX); - -// if ((axh & 0x3f) == 0) -// shift = 0; -// else if (axh & 0x40) -// shift = -0x40 + (axh & 0x3f); -// else -// shift = axh & 0x3f; - -// if (shift > 0) { -// acc <<= shift; -// } else if (shift < 0) { -// acc >>= -shift; -// } - - CMP(64, R(RDX), Imm8(0)); - FixupBranch zero = J_CC(CC_E); - TEST(16, R(RAX), Imm16(0x3f)); - FixupBranch noShift = J_CC(CC_Z); - MOVZX(64, 16, RCX, R(RAX)); - AND(16, R(RCX), Imm16(0x3f)); - TEST(16, R(RAX), Imm16(0x40)); - FixupBranch shiftLeft = J_CC(CC_Z); - NEG(16, R(RCX)); - ADD(16, R(RCX), Imm16(0x40)); - SAR(64, R(RDX), R(RCX)); - FixupBranch exit = J(); - SetJumpTarget(shiftLeft); - SHL(64, R(RDX), R(RCX)); - SetJumpTarget(noShift); - SetJumpTarget(exit); - -// dsp_set_long_acc(dreg, acc); - set_long_acc(dreg, RDX); - SetJumpTarget(zero); -// Update_SR_Register64(dsp_get_long_acc(dreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RDX); - } -#else - Default(opc); -#endif -} - -// LSRNR $acD -// 0011 110d 1xxx xxxx -// Logically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::lsrnr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - -// s16 shift; -// u16 accm = (u16)dsp_get_acc_m(1 - dreg); - get_acc_m(1 - dreg); -// u64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg, RDX); -// acc &= 0x000000FFFFFFFFFFULL; - SHL(64, R(RDX), Imm8(24)); - SHR(64, R(RDX), Imm8(24)); - -// if ((accm & 0x3f) == 0) -// shift = 0; -// else if (accm & 0x40) -// shift = -0x40 + (accm & 0x3f); -// else -// shift = accm & 0x3f; - -// if (shift > 0) -// acc <<= shift; -// else if (shift < 0) -// acc >>= -shift; - - CMP(64, R(RDX), Imm8(0)); - FixupBranch zero = J_CC(CC_E); - TEST(16, R(RAX), Imm16(0x3f)); - FixupBranch noShift = J_CC(CC_Z); - MOVZX(64, 16, RCX, R(RAX)); - AND(16, R(RCX), Imm16(0x3f)); - TEST(16, R(RAX), Imm16(0x40)); - FixupBranch shiftLeft = J_CC(CC_Z); - NEG(16, R(RCX)); - ADD(16, R(RCX), Imm16(0x40)); - SAR(64, R(RDX), R(RCX)); - FixupBranch exit = J(); - SetJumpTarget(shiftLeft); - SHL(64, R(RDX), R(RCX)); - SetJumpTarget(noShift); - SetJumpTarget(exit); - -// dsp_set_long_acc(dreg, (s64)acc); - set_long_acc(dreg, RDX); - SetJumpTarget(zero); -// Update_SR_Register64(dsp_get_long_acc(dreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RDX); - } -#else - Default(opc); -#endif -} - -// ASRNR $acD -// 0011 111d 1xxx xxxx -// Arithmetically shift left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M -// x = extension (7 bits!!) -// -// flags out: --xx xx00 -void DSPEmitter::asrnr(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - -// s16 shift; -// u16 accm = (u16)dsp_get_acc_m(1 - dreg); - get_acc_m(1 - dreg); -// s64 acc = dsp_get_long_acc(dreg); - get_long_acc(dreg); - -// if ((accm & 0x3f) == 0) -// shift = 0; -// else if (accm & 0x40) -// shift = -0x40 + (accm & 0x3f); -// else -// shift = accm & 0x3f; - -// if (shift > 0) -// acc <<= shift; -// else if (shift < 0) -// acc >>= -shift; - - CMP(64, R(RDX), Imm8(0)); - FixupBranch zero = J_CC(CC_E); - TEST(16, R(RAX), Imm16(0x3f)); - FixupBranch noShift = J_CC(CC_Z); - MOVZX(64, 16, RCX, R(RAX)); - AND(16, R(RCX), Imm16(0x3f)); - TEST(16, R(RAX), Imm16(0x40)); - FixupBranch shiftLeft = J_CC(CC_Z); - NEG(16, R(RCX)); - ADD(16, R(RCX), Imm16(0x40)); - SAR(64, R(RDX), R(RCX)); - FixupBranch exit = J(); - SetJumpTarget(shiftLeft); - SHL(64, R(RDX), R(RCX)); - SetJumpTarget(noShift); - SetJumpTarget(exit); - -// dsp_set_long_acc(dreg, acc); - set_long_acc(dreg, RDX); - SetJumpTarget(zero); -// Update_SR_Register64(dsp_get_long_acc(dreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RDX); - } -#else - Default(opc); -#endif -} - - -//} // namespace - -// diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp deleted file mode 100644 index 4dd2476e70..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp +++ /dev/null @@ -1,606 +0,0 @@ -// Copyright (C) 2010 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 "../DSPMemoryMap.h" -#include "../DSPEmitter.h" -#include "../DSPStacks.h" -#include "../DSPAnalyzer.h" -#include "DSPJitUtil.h" -#include "x64Emitter.h" -#include "ABI.h" - -using namespace Gen; - -template <void(*jitCode)(const UDSPInstruction, DSPEmitter&)> -static void ReJitConditional(const UDSPInstruction opc, DSPEmitter& emitter) -{ - u8 cond = opc & 0xf; - if (cond == 0xf) {// Always true. - jitCode(opc,emitter); - return; - } - FixupBranch skipCode2; - emitter.dsp_op_read_reg(DSP_REG_SR, RAX); - DSPJitRegCache c2(emitter.gpr); - switch(cond) - { - case 0x0: // GE - Greater Equal - case 0x1: // L - Less - case 0x2: // G - Greater - case 0x3: // LE - Less Equal - emitter.MOV(16, R(EDX), R(EAX)); - emitter.SHR(16, R(EDX), Imm8(3)); //SR_SIGN flag - emitter.NOT(16, R(EDX)); - emitter.SHR(16, R(EAX), Imm8(1)); //SR_OVERFLOW flag - emitter.NOT(16, R(EAX)); - emitter.XOR(16, R(EAX), R(EDX)); - if (cond < 0x2) { - emitter.TEST(16, R(EAX), Imm16(1)); - break; - } - c2 = emitter.gpr; - emitter.TEST(16, R(EAX), Imm16(1)); - - //LE: problem in here, half the tests fail - skipCode2 = emitter.J_CC(CC_NE); - //skipCode2 = emitter.J_CC((CCFlags)(CC_NE - (cond & 1))); - emitter.dsp_op_read_reg(DSP_REG_SR, RAX); - emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO)); - break; - case 0x4: // NZ - Not Zero - case 0x5: // Z - Zero - emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO)); - break; - case 0x6: // NC - Not carry - case 0x7: // C - Carry - emitter.TEST(16, R(EAX), Imm16(SR_CARRY)); - break; - case 0x8: // ? - Not over s32 - case 0x9: // ? - Over s32 - emitter.TEST(16, R(EAX), Imm16(SR_OVER_S32)); - break; - case 0xa: // ? - case 0xb: // ? - { - //full of fail, both - emitter.TEST(16, R(EAX), Imm16(SR_OVER_S32 | SR_TOP2BITS)); - FixupBranch skipArithZero = emitter.J_CC(CC_E); - emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO)); - FixupBranch setZero = emitter.J_CC(CC_NE); - - emitter.MOV(16, R(EAX), Imm16(1)); - FixupBranch toEnd = emitter.J(); - - emitter.SetJumpTarget(skipArithZero); - emitter.SetJumpTarget(setZero); - emitter.XOR(16, R(EAX), R(EAX)); - emitter.SetJumpTarget(toEnd); - emitter.SETcc(CC_E, R(EAX)); - emitter.TEST(8, R(EAX), R(EAX)); - break; - //c2 = emitter.gpr; - //emitter.TEST(16, R(EAX), Imm16(SR_OVER_S32 | SR_TOP2BITS)); - //skipCode2 = emitter.J_CC((CCFlags)(CC_E + (cond & 1))); - //emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO)); - //break; - } - case 0xc: // LNZ - Logic Not Zero - case 0xd: // LZ - Logic Zero - emitter.TEST(16, R(EAX), Imm16(SR_LOGIC_ZERO)); - break; - case 0xe: // 0 - Overflow - emitter.TEST(16, R(EAX), Imm16(SR_OVERFLOW)); - break; - } - DSPJitRegCache c1(emitter.gpr); - FixupBranch skipCode = cond == 0xe ? emitter.J_CC(CC_E) : emitter.J_CC((CCFlags)(CC_NE - (cond & 1))); - jitCode(opc,emitter); - emitter.gpr.flushRegs(c1); - emitter.SetJumpTarget(skipCode); - if ((cond | 1) == 0x3) {// || (cond | 1) == 0xb) - emitter.gpr.flushRegs(c2); - emitter.SetJumpTarget(skipCode2); - } else { - c2.drop(); - } -} - -static void WriteBranchExit(DSPEmitter& emitter) -{ - emitter.SaveDSPRegs(); - if (DSPAnalyzer::code_flags[emitter.startAddr] & DSPAnalyzer::CODE_IDLE_SKIP) - { - emitter.MOV(16, R(EAX), Imm16(0x1000)); - } - else - { - emitter.MOV(16, R(EAX), Imm16(emitter.blockSize[emitter.startAddr])); - } - emitter.JMP(emitter.returnDispatcher, true); -} - -static void WriteBlockLink(DSPEmitter& emitter, u16 dest) -{ - // Jump directly to the called block if it has already been compiled. - if (!(dest >= emitter.startAddr && dest <= emitter.compilePC)) - { - if (emitter.blockLinks[dest] != 0 ) - { - emitter.gpr.flushRegs(); -#ifdef _M_IX86 // All32 - // Check if we have enough cycles to execute the next block - emitter.MOV(16, R(ESI), M(&cyclesLeft)); - emitter.CMP(16, R(ESI), Imm16(emitter.blockSize[emitter.startAddr] + emitter.blockSize[dest])); - FixupBranch notEnoughCycles = emitter.J_CC(CC_BE); - - emitter.SUB(16, R(ESI), Imm16(emitter.blockSize[emitter.startAddr])); - emitter.MOV(16, M(&cyclesLeft), R(ESI)); -#else - // Check if we have enough cycles to execute the next block - emitter.MOV(64, R(R12), ImmPtr(&cyclesLeft)); - emitter.CMP(16, MatR(R12), Imm16(emitter.blockSize[emitter.startAddr] + emitter.blockSize[dest])); - FixupBranch notEnoughCycles = emitter.J_CC(CC_BE); - - emitter.SUB(16, MatR(R12), Imm16(emitter.blockSize[emitter.startAddr])); -#endif - emitter.JMP(emitter.blockLinks[dest], true); - emitter.SetJumpTarget(notEnoughCycles); - } - else - { - // The destination has not been compiled yet. Add it to the list - // of blocks that this block is waiting on. - emitter.unresolvedJumps[emitter.startAddr].push_back(dest); - } - } -} - -void r_jcc(const UDSPInstruction opc, DSPEmitter& emitter) -{ - u16 dest = dsp_imem_read(emitter.compilePC + 1); - const DSPOPCTemplate *opcode = GetOpTemplate(opc); - - // If the block is unconditional, attempt to link block - if (opcode->uncond_branch) - WriteBlockLink(emitter, dest); -#ifdef _M_IX86 // All32 - emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest)); -#else - emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - emitter.MOV(16, MatR(RAX), Imm16(dest)); -#endif - WriteBranchExit(emitter); -} -// 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. -// NOTE: Cannot use Default(opc) here because of the need to write branch exit -void DSPEmitter::jcc(const UDSPInstruction opc) -{ -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 2)); -#endif - ReJitConditional<r_jcc>(opc, *this); -} - -void r_jmprcc(const UDSPInstruction opc, DSPEmitter& emitter) -{ - u8 reg = (opc >> 5) & 0x7; - //reg can only be DSP_REG_ARx and DSP_REG_IXx now, - //no need to handle DSP_REG_STx. - emitter.dsp_op_read_reg(reg, RAX, NONE); -#ifdef _M_IX86 // All32 - emitter.MOV(16, M(&g_dsp.pc), R(EAX)); -#else - emitter.MOV(64, R(RSI), ImmPtr(&(g_dsp.pc))); - emitter.MOV(16, MatR(RSI), R(RAX)); -#endif - WriteBranchExit(emitter); -} -// Generic jmpr implementation -// JMPcc $R -// 0001 0111 rrr0 cccc -// Jump to address; set program counter to a value from register $R. -// NOTE: Cannot use Default(opc) here because of the need to write branch exit -void DSPEmitter::jmprcc(const UDSPInstruction opc) -{ -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.pc), Imm16(compilePC + 1)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 1)); -#endif - ReJitConditional<r_jmprcc>(opc, *this); -} - -void r_call(const UDSPInstruction opc, DSPEmitter& emitter) -{ - emitter.MOV(16, R(DX), Imm16(emitter.compilePC + 2)); - emitter.dsp_reg_store_stack(DSP_STACK_C); - u16 dest = dsp_imem_read(emitter.compilePC + 1); - const DSPOPCTemplate *opcode = GetOpTemplate(opc); - - // If the block is unconditional, attempt to link block - if (opcode->uncond_branch) - WriteBlockLink(emitter, dest); -#ifdef _M_IX86 // All32 - emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest)); -#else - emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - emitter.MOV(16, MatR(RAX), Imm16(dest)); -#endif - WriteBranchExit(emitter); -} -// 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. -// NOTE: Cannot use Default(opc) here because of the need to write branch exit -void DSPEmitter::call(const UDSPInstruction opc) -{ -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 2)); -#endif - ReJitConditional<r_call>(opc, *this); -} - -void r_callr(const UDSPInstruction opc, DSPEmitter& emitter) -{ - u8 reg = (opc >> 5) & 0x7; - emitter.MOV(16, R(DX), Imm16(emitter.compilePC + 1)); - emitter.dsp_reg_store_stack(DSP_STACK_C); - emitter.dsp_op_read_reg(reg, RAX, NONE); -#ifdef _M_IX86 // All32 - emitter.MOV(16, M(&g_dsp.pc), R(EAX)); -#else - emitter.MOV(64, R(RSI), ImmPtr(&(g_dsp.pc))); - emitter.MOV(16, MatR(RSI), R(RAX)); -#endif - WriteBranchExit(emitter); -} -// 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. -// NOTE: Cannot use Default(opc) here because of the need to write branch exit -void DSPEmitter::callr(const UDSPInstruction opc) -{ -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.pc), Imm16(compilePC + 1)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 1)); -#endif - ReJitConditional<r_callr>(opc, *this); -} - -void r_ifcc(const UDSPInstruction opc, DSPEmitter& emitter) -{ -#ifdef _M_IX86 // All32 - emitter.MOV(16, M(&g_dsp.pc), Imm16(emitter.compilePC + 1)); -#else - emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - emitter.MOV(16, MatR(RAX), Imm16(emitter.compilePC + 1)); -#endif -} -// Generic if implementation -// IFcc -// 0000 0010 0111 cccc -// Execute following opcode if the condition has been met. -// NOTE: Cannot use Default(opc) here because of the need to write branch exit -void DSPEmitter::ifcc(const UDSPInstruction opc) -{ -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.pc), Imm16((compilePC + 1) + opTable[compilePC + 1]->size)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16((compilePC + 1) + opTable[compilePC + 1]->size)); -#endif - ReJitConditional<r_ifcc>(opc, *this); - WriteBranchExit(*this); -} - -void r_ret(const UDSPInstruction opc, DSPEmitter& emitter) -{ - emitter.dsp_reg_load_stack(DSP_STACK_C); -#ifdef _M_IX86 // All32 - emitter.MOV(16, M(&g_dsp.pc), R(DX)); -#else - emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - emitter.MOV(16, MatR(RAX), R(DX)); -#endif - WriteBranchExit(emitter); -} - -// 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. -// NOTE: Cannot use Default(opc) here because of the need to write branch exit -void DSPEmitter::ret(const UDSPInstruction opc) -{ -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.pc), Imm16(compilePC + 1)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 1)); -#endif - ReJitConditional<r_ret>(opc, *this); -} - -// 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 DSPEmitter::rti(const UDSPInstruction opc) -{ -// g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D); - dsp_reg_load_stack(DSP_STACK_D); - dsp_op_write_reg(DSP_REG_SR, RDX); -// g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C); - dsp_reg_load_stack(DSP_STACK_C); -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.pc), R(DX)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), R(DX)); -#endif -} - -// HALT -// 0000 0000 0020 0001 -// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR. -void DSPEmitter::halt(const UDSPInstruction opc) -{ -#ifdef _M_IX86 // All32 - OR(16, M(&g_dsp.cr), Imm16(4)); -#else - MOV(64, R(RAX), ImmPtr(&g_dsp.cr)); - OR(16, MatR(RAX), Imm16(4)); -#endif - // g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C); - dsp_reg_load_stack(DSP_STACK_C); -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.pc), R(DX)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), R(DX)); -#endif -} - -// 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 value from call stack $st0. Otherwise values from -// call stack $st0 and both loop stacks $st2 and $st3 are popped and execution -// continues at next opcode. -void DSPEmitter::HandleLoop() -{ -#ifdef _M_IX86 // All32 - MOVZX(32, 16, EAX, M(&g_dsp.r.st[2])); - MOVZX(32, 16, ECX, M(&g_dsp.r.st[3])); -#else - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[2]))); - MOVZX(32, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[3]))); -#endif - - CMP(32, R(RCX), Imm32(0)); - FixupBranch rLoopCntG = J_CC(CC_LE, true); - CMP(16, R(RAX), Imm16(compilePC - 1)); - FixupBranch rLoopAddrG = J_CC(CC_NE, true); - -#ifdef _M_IX86 // All32 - SUB(16, M(&(g_dsp.r.st[3])), Imm16(1)); - CMP(16, M(&(g_dsp.r.st[3])), Imm16(0)); -#else - SUB(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[3])), Imm16(1)); - CMP(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[3])), Imm16(0)); -#endif - - FixupBranch loadStack = J_CC(CC_LE, true); -#ifdef _M_IX86 // All32 - MOVZX(32, 16, ECX, M(&(g_dsp.r.st[0]))); - MOV(16, M(&g_dsp.pc), R(RCX)); -#else - MOVZX(32, 16, RCX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[0]))); - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), R(RCX)); -#endif - FixupBranch loopUpdated = J(true); - - SetJumpTarget(loadStack); - dsp_reg_load_stack(0); - dsp_reg_load_stack(2); - dsp_reg_load_stack(3); - - SetJumpTarget(loopUpdated); - SetJumpTarget(rLoopAddrG); - SetJumpTarget(rLoopCntG); - -} - -// 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 DSPEmitter::loop(const UDSPInstruction opc) -{ - u16 reg = opc & 0x1f; -// u16 cnt = g_dsp.r[reg]; - dsp_op_read_reg(reg, RDX, ZERO); - u16 loop_pc = compilePC + 1; - - CMP(16, R(EDX), Imm16(0)); - FixupBranch cnt = J_CC(CC_Z, true); - dsp_reg_store_stack(3); - MOV(16, R(RDX), Imm16(compilePC + 1)); - dsp_reg_store_stack(0); - MOV(16, R(RDX), Imm16(loop_pc)); - dsp_reg_store_stack(2); - - SetJumpTarget(cnt); -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 1)); -#endif -} - -// 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 DSPEmitter::loopi(const UDSPInstruction opc) -{ - u16 cnt = opc & 0xff; - u16 loop_pc = compilePC + 1; - - if (cnt) - { - MOV(16, R(RDX), Imm16(compilePC + 1)); - dsp_reg_store_stack(0); - MOV(16, R(RDX), Imm16(loop_pc)); - dsp_reg_store_stack(2); - MOV(16, R(RDX), Imm16(cnt)); - dsp_reg_store_stack(3); - -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 1)); -#endif - } -} - - -// 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 are allowed. -void DSPEmitter::bloop(const UDSPInstruction opc) -{ - u16 reg = opc & 0x1f; -// u16 cnt = g_dsp.r[reg]; - dsp_op_read_reg(reg, RDX, ZERO); - u16 loop_pc = dsp_imem_read(compilePC + 1); - - CMP(16, R(EDX), Imm16(0)); - FixupBranch cnt = J_CC(CC_Z, true); - dsp_reg_store_stack(3); - MOV(16, R(RDX), Imm16(compilePC + 2)); - dsp_reg_store_stack(0); - MOV(16, R(RDX), Imm16(loop_pc)); - dsp_reg_store_stack(2); -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 2)); -#endif - FixupBranch exit = J(); - - SetJumpTarget(cnt); - // g_dsp.pc = loop_pc; - // dsp_skip_inst(); -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[loop_pc]->size)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(loop_pc + opTable[loop_pc]->size)); -#endif - DSPJitRegCache c(gpr); - WriteBranchExit(*this); - gpr.flushRegs(c,false); - SetJumpTarget(exit); -} - -// 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 are allowed. -void DSPEmitter::bloopi(const UDSPInstruction opc) -{ - u16 cnt = opc & 0xff; -// u16 loop_pc = dsp_fetch_code(); - u16 loop_pc = dsp_imem_read(compilePC + 1); - - if (cnt) - { - MOV(16, R(RDX), Imm16(compilePC + 2)); - dsp_reg_store_stack(0); - MOV(16, R(RDX), Imm16(loop_pc)); - dsp_reg_store_stack(2); - MOV(16, R(RDX), Imm16(cnt)); - dsp_reg_store_stack(3); - -#ifdef _M_IX86 // All32 - MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(compilePC + 2)); -#endif - } - else - { -// g_dsp.pc = loop_pc; -// dsp_skip_inst(); -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[loop_pc]->size)); -#else - MOV(64, R(RAX), ImmPtr(&(g_dsp.pc))); - MOV(16, MatR(RAX), Imm16(loop_pc + opTable[loop_pc]->size)); -#endif - WriteBranchExit(*this); - } -} diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitCCUtil.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitCCUtil.cpp deleted file mode 100644 index 620c2a2c43..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitCCUtil.cpp +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (C) 2003 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 "../DSPIntUtil.h" -#include "../DSPEmitter.h" -#include "x64Emitter.h" -#include "ABI.h" -using namespace Gen; - -// In: RAX: s64 _Value -// In: RCX: 1 = carry, 2 = overflow -// Clobbers RDX -void DSPEmitter::Update_SR_Register(Gen::X64Reg val) -{ -#ifdef _M_X64 - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - // // 0x04 - // if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO; - CMP(64, R(val), Imm8(0)); - FixupBranch notZero = J_CC(CC_NZ); - OR(16, sr_reg, Imm16(SR_ARITH_ZERO)); - SetJumpTarget(notZero); - - // // 0x08 - // if (_Value < 0) g_dsp.r[DSP_REG_SR] |= SR_SIGN; - CMP(64, R(val), Imm8(0)); - FixupBranch greaterThanEqual = J_CC(CC_GE); - OR(16, sr_reg, Imm16(SR_SIGN)); - SetJumpTarget(greaterThanEqual); - - // // 0x10 - // if (_Value != (s32)_Value) g_dsp.r[DSP_REG_SR] |= SR_OVER_S32; - MOVSX(64, 32, RDX, R(val)); - CMP(64, R(RDX), R(val)); - FixupBranch noOverS32 = J_CC(CC_E); - OR(16, sr_reg, Imm16(SR_OVER_S32)); - SetJumpTarget(noOverS32); - - // // 0x20 - Checks if top bits of m are equal - // if (((_Value & 0xc0000000) == 0) || ((_Value & 0xc0000000) == 0xc0000000)) - AND(32, R(val), Imm32(0xc0000000)); - CMP(32, R(val), Imm32(0)); - FixupBranch zeroC = J_CC(CC_E); - CMP(32, R(val), Imm32(0xc0000000)); - FixupBranch cC = J_CC(CC_NE); - SetJumpTarget(zeroC); - // g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS; - OR(16, sr_reg, Imm16(SR_TOP2BITS)); - SetJumpTarget(cC); - gpr.putReg(DSP_REG_SR); -#endif -} - -// In: RAX: s64 _Value -// In: RCX: 1 = carry, 2 = overflow -// Clobbers RDX -void DSPEmitter::Update_SR_Register64(Gen::X64Reg val) -{ -#ifdef _M_X64 -// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK; - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - AND(16, sr_reg, Imm16(~SR_CMP_MASK)); - gpr.putReg(DSP_REG_SR); - Update_SR_Register(val); -#endif -} - -// In: RAX: s64 _Value -// In: RCX: 1 = carry, 2 = overflow -// Clobbers RDX -void DSPEmitter::Update_SR_Register64_Carry(Gen::X64Reg val) -{ -#ifdef _M_X64 - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - // g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK; - AND(16, sr_reg, Imm16(~SR_CMP_MASK)); - - CMP(64, R(RCX), R(val)); - - // 0x01 - // g_dsp.r[DSP_REG_SR] |= SR_CARRY; - // Carry = (acc>res) - FixupBranch noCarry = J_CC(CC_BE); - OR(16, sr_reg, Imm16(SR_CARRY)); - SetJumpTarget(noCarry); - - // 0x02 and 0x80 - // g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW; - // g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW_STICKY; - // Overflow = ((acc ^ res) & (ax ^ res)) < 0 - XOR(64, R(RCX), R(val)); - XOR(64, R(RDX), R(val)); - AND(64, R(RCX), R(RDX)); - CMP(64, R(RCX), Imm8(0)); - FixupBranch noOverflow = J_CC(CC_GE); - OR(16, sr_reg, Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY)); - SetJumpTarget(noOverflow); - - gpr.putReg(DSP_REG_SR); - Update_SR_Register(val); -#endif -} - -// In: RAX: s64 _Value -// In: RCX: 1 = carry, 2 = overflow -// Clobbers RDX -void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val) -{ -#ifdef _M_X64 - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - // g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK; - AND(16, sr_reg, Imm16(~SR_CMP_MASK)); - - CMP(64, R(RCX), R(val)); - - // 0x01 - // g_dsp.r[DSP_REG_SR] |= SR_CARRY; - // Carry2 = (acc>=res) - FixupBranch noCarry2 = J_CC(CC_B); - OR(16, sr_reg, Imm16(SR_CARRY)); - SetJumpTarget(noCarry2); - - // 0x02 and 0x80 - // g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW; - // g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW_STICKY; - // Overflow = ((acc ^ res) & (ax ^ res)) < 0 - XOR(64, R(RCX), R(val)); - XOR(64, R(RDX), R(val)); - AND(64, R(RCX), R(RDX)); - CMP(64, R(RCX), Imm8(0)); - FixupBranch noOverflow = J_CC(CC_GE); - OR(16, sr_reg, Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY)); - SetJumpTarget(noOverflow); - gpr.putReg(DSP_REG_SR); - - Update_SR_Register(); -#endif -} - -//void DSPEmitter::Update_SR_Register16(s16 _Value, bool carry, bool overflow, bool overS32) -//{ - -// // 0x20 - Checks if top bits of m are equal -// if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3)) -// { -// g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS; -// } -//} - -// In: RAX: s64 _Value -// In: RCX: 1 = carry, 2 = overflow -// Clobbers RDX -void DSPEmitter::Update_SR_Register16(Gen::X64Reg val) -{ -#ifdef _M_X64 - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - AND(16, sr_reg, Imm16(~SR_CMP_MASK)); - - // // 0x04 - // if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO; - CMP(64, R(val), Imm8(0)); - FixupBranch notZero = J_CC(CC_NZ); - OR(16, sr_reg, Imm16(SR_ARITH_ZERO)); - SetJumpTarget(notZero); - - // // 0x08 - // if (_Value < 0) g_dsp.r[DSP_REG_SR] |= SR_SIGN; - CMP(64, R(val), Imm8(0)); - FixupBranch greaterThanEqual = J_CC(CC_GE); - OR(16, sr_reg, Imm16(SR_SIGN)); - SetJumpTarget(greaterThanEqual); - - // // 0x20 - Checks if top bits of m are equal - // if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3)) - //AND(32, R(val), Imm32(0xc0000000)); - SHR(16, R(val), Imm8(14)); - CMP(16, R(val), Imm16(0)); - FixupBranch nZero = J_CC(CC_NE); - OR(16, sr_reg, Imm16(SR_TOP2BITS)); - FixupBranch cC = J(); - SetJumpTarget(nZero); - CMP(16, R(val), Imm16(3)); - FixupBranch notThree = J_CC(CC_NE); - // g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS; - OR(16, sr_reg, Imm16(SR_TOP2BITS)); - SetJumpTarget(notThree); - SetJumpTarget(cC); - gpr.putReg(DSP_REG_SR); -#endif -} - -// In: RAX: s64 _Value -// In: RCX: 1 = carry, 2 = overflow -// Clobbers RDX -void DSPEmitter::Update_SR_Register16_OverS32(Gen::X64Reg val) -{ -#ifdef _M_X64 - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - AND(16, sr_reg, Imm16(~SR_CMP_MASK)); - - // // 0x10 - // if (_Value != (s32)_Value) g_dsp.r[DSP_REG_SR] |= SR_OVER_S32; - MOVSX(64, 32, RSI, R(val)); - CMP(64, R(RSI), R(val)); - FixupBranch noOverS32 = J_CC(CC_E); - OR(16, sr_reg, Imm16(SR_OVER_S32)); - SetJumpTarget(noOverS32); - - gpr.putReg(DSP_REG_SR); - // // 0x20 - Checks if top bits of m are equal - // if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3)) - //AND(32, R(val), Imm32(0xc0000000)); - Update_SR_Register16(val); -#endif -} - -//void DSPEmitter::Update_SR_LZ(bool value) { - -// if (value == true) -// g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO; -// else -// g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO; -//} - -//inline int GetMultiplyModifier() -//{ -// return (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)?1:2; -//} - -//inline bool isCarry() { -// return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false; -//} - -//inline bool isOverflow() { -// return (g_dsp.r[DSP_REG_SR] & SR_OVERFLOW) ? true : false; -//} - -//inline bool isOverS32() { -// return (g_dsp.r[DSP_REG_SR] & SR_OVER_S32) ? true : false; -//} - -//inline bool isLess() { -// return (!(g_dsp.r[DSP_REG_SR] & SR_OVERFLOW) != !(g_dsp.r[DSP_REG_SR] & SR_SIGN)); -//} - -//inline bool isZero() { -// return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false; -//} - -//inline bool isLogicZero() { -// return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) ? true : false; -//} - -//inline bool isConditionA() { -// return (((g_dsp.r[DSP_REG_SR] & SR_OVER_S32) || (g_dsp.r[DSP_REG_SR] & SR_TOP2BITS)) && !(g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO)) ? true : false; -//} - -//see DSPCore.h for flags -//bool CheckCondition(u8 _Condition) -//{ -// switch (_Condition & 0xf) -// { -// case 0xf: // Always true. -// return true; -// case 0x0: // GE - Greater Equal -// return !isLess(); -// case 0x1: // L - Less -// return isLess(); -// case 0x2: // G - Greater -// return !isLess() && !isZero(); -// case 0x3: // LE - Less Equal -// return isLess() || isZero(); -// case 0x4: // NZ - Not Zero -// return !isZero(); -// case 0x5: // Z - Zero -// return isZero(); -// case 0x6: // NC - Not carry -// return !isCarry(); -// case 0x7: // C - Carry -// return isCarry(); -// case 0x8: // ? - Not over s32 -// return !isOverS32(); -// case 0x9: // ? - Over s32 -// return isOverS32(); -// case 0xa: // ? -// return isConditionA(); -// case 0xb: // ? -// return !isConditionA(); -// case 0xc: // LNZ - Logic Not Zero -// return !isLogicZero(); -// case 0xd: // LZ - Logic Zero -// return isLogicZero(); -// case 0xe: // 0 - Overflow -// return isOverflow(); -// default: -// return true; -// } -//} diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp deleted file mode 100644 index 084385e2e4..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp +++ /dev/null @@ -1,639 +0,0 @@ -// Copyright (C) 2010 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 "../DSPMemoryMap.h" -#include "../DSPEmitter.h" -#include "DSPJitUtil.h" -#include "x64Emitter.h" -#include "ABI.h" - -using namespace Gen; - -/* It is safe to directly write to the address registers as they are - neither read not written by any extendable opcode. The same is true - for memory accesses. - It probably even is safe to write to all registers except for - SR, ACx.x, AXx.x and PROD, which may be modified by the main op. - - This code uses EBX to keep the values of the registers written by - the extended op so the main op can still access the old values. - storeIndex and storeIndex2 control where the lower and upper 16bits - of EBX are written to. Additionally, the upper 16bits can contain the - original SR so we can do sign extension in 40bit mode. There is only - the 'ld family of opcodes writing to two registers at the same time, - and those always are AXx.x, thus no need to leave space for SR for - sign extension. - */ - -// DR $arR -// xxxx xxxx 0000 01rr -// Decrement addressing register $arR. -void DSPEmitter::dr(const UDSPInstruction opc) { - decrement_addr_reg(opc & 0x3); -} - -// IR $arR -// xxxx xxxx 0000 10rr -// Increment addressing register $arR. -void DSPEmitter::ir(const UDSPInstruction opc) { - increment_addr_reg(opc & 0x3); -} - -// NR $arR -// xxxx xxxx 0000 11rr -// Add corresponding indexing register $ixR to addressing register $arR. -void DSPEmitter::nr(const UDSPInstruction opc) { - u8 reg = opc & 0x3; - - increase_addr_reg(reg); -} - -// MV $axD.D, $acS.S -// xxxx xxxx 0001 ddss -// Move value of $acS.S to the $axD.D. -void DSPEmitter::mv(const UDSPInstruction opc) -{ - u8 sreg = (opc & 0x3) + DSP_REG_ACL0; - u8 dreg = ((opc >> 2) & 0x3); - pushExtValueFromReg(dreg + DSP_REG_AXL0, sreg); -} - -// S @$arD, $acS.S -// xxxx xxxx 001s s0dd -// Store value of $acS.S in the memory pointed by register $arD. -// Post increment register $arD. -void DSPEmitter::s(const UDSPInstruction opc) -{ - u8 dreg = opc & 0x3; - u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0; - // u16 addr = g_dsp.r[dest]; - dsp_op_read_reg(dreg, RAX, ZERO); - dsp_op_read_reg(sreg, RCX, ZERO); - // u16 val = g_dsp.r[src]; - dmem_write(); - increment_addr_reg(dreg); -} - -// SN @$arD, $acS.S -// xxxx xxxx 001s s1dd -// Store value of register $acS.S in the memory pointed by register $arD. -// Add indexing register $ixD to register $arD. -void DSPEmitter::sn(const UDSPInstruction opc) -{ - u8 dreg = opc & 0x3; - u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0; - dsp_op_read_reg(dreg, RAX, ZERO); - dsp_op_read_reg(sreg, RCX, ZERO); - dmem_write(); - increase_addr_reg(dreg); -} - -// L $axD.D, @$arS -// xxxx xxxx 01dd d0ss -// Load $axD.D/$acD.D with value from memory pointed by register $arS. -// Post increment register $arS. -void DSPEmitter::l(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x3; - u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0; //AX?.?, AC?.[LM] - - pushExtValueFromMem(dreg, sreg); - - if (dreg >= DSP_REG_ACM0) { - //save SR too, so we can decide later. - //even if only for one bit, can only - //store (up to) two registers in EBX, - //so store all of SR -#ifdef _M_IX86 // All32 - MOV(16, R(EAX), M(&g_dsp.r.sr)); -#else - MOV(64, R(RAX), ImmPtr(&g_dsp.r.sr)); - MOV(16, R(RAX), MatR(RAX)); -#endif - SHL(32, R(EAX), Imm8(16)); - OR(32, R(EBX), R(EAX)); - } - - increment_addr_reg(sreg); -} - -// LN $axD.D, @$arS -// xxxx xxxx 01dd d0ss -// Load $axD.D/$acD.D with value from memory pointed by register $arS. -// Add indexing register register $ixS to register $arS. -void DSPEmitter::ln(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x3; - u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0; - - pushExtValueFromMem(dreg, sreg); - - if (dreg >= DSP_REG_ACM0) { - //save SR too, so we can decide later. - //even if only for one bit, can only - //store (up to) two registers in EBX, - //so store all of SR -#ifdef _M_IX86 // All32 - MOV(16, R(EAX), M(&g_dsp.r.sr)); -#else - MOV(64, R(RAX), ImmPtr(&g_dsp.r.sr)); - MOV(16, R(RAX), MatR(RAX)); -#endif - SHL(32, R(EAX), Imm8(16)); - OR(32, R(EBX), R(EAX)); - } - - increase_addr_reg(sreg); -} - -// LS $axD.D, $acS.m -// xxxx xxxx 10dd 000s -// Load register $axD.D with value from memory pointed by register -// $ar0. Store value from register $acS.m to memory location pointed by -// register $ar3. Increment both $ar0 and $ar3. -void DSPEmitter::ls(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - dsp_op_read_reg(DSP_REG_AR3, RAX, ZERO); - get_acc_m(sreg, ECX, false); - dmem_write(); - - pushExtValueFromMem(dreg, DSP_REG_AR0); - - increment_addr_reg(DSP_REG_AR3); - increment_addr_reg(DSP_REG_AR0); -} - - -// LSN $axD.D, $acS.m -// xxxx xxxx 10dd 010s -// Load register $axD.D with value from memory pointed by register -// $ar0. Store value from register $acS.m to memory location pointed by -// register $ar3. Add corresponding indexing register $ix0 to addressing -// register $ar0 and increment $ar3. -void DSPEmitter::lsn(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - dsp_op_read_reg(DSP_REG_AR3, RAX, ZERO); - get_acc_m(sreg, ECX, false); - dmem_write(); - - pushExtValueFromMem(dreg, DSP_REG_AR0); - - increment_addr_reg(DSP_REG_AR3); - increase_addr_reg(DSP_REG_AR0); -} - -// LSM $axD.D, $acS.m -// xxxx xxxx 10dd 100s -// Load register $axD.D with value from memory pointed by register -// $ar0. Store value from register $acS.m to memory location pointed by -// register $ar3. Add corresponding indexing register $ix3 to addressing -// register $ar3 and increment $ar0. -void DSPEmitter::lsm(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - dsp_op_read_reg(DSP_REG_AR3, RAX, ZERO); - get_acc_m(sreg, ECX, false); - dmem_write(); - - pushExtValueFromMem(dreg, DSP_REG_AR0); - - increase_addr_reg(DSP_REG_AR3); - increment_addr_reg(DSP_REG_AR0); -} - -// LSMN $axD.D, $acS.m -// xxxx xxxx 10dd 110s -// Load register $axD.D with value from memory pointed by register -// $ar0. Store value from register $acS.m to memory location pointed by -// register $ar3. Add corresponding indexing register $ix0 to addressing -// register $ar0 and add corresponding indexing register $ix3 to addressing -// register $ar3. -void DSPEmitter::lsnm(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - dsp_op_read_reg(DSP_REG_AR3, RAX, ZERO); - get_acc_m(sreg, ECX, false); - dmem_write(); - - pushExtValueFromMem(dreg, DSP_REG_AR0); - - increase_addr_reg(DSP_REG_AR3); - increase_addr_reg(DSP_REG_AR0); -} - -// SL $acS.m, $axD.D -// xxxx xxxx 10dd 001s -// Store value from register $acS.m to memory location pointed by register -// $ar0. Load register $axD.D with value from memory pointed by register -// $ar3. Increment both $ar0 and $ar3. -void DSPEmitter::sl(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - dsp_op_read_reg(DSP_REG_AR0, RAX, ZERO); - get_acc_m(sreg, ECX, false); - dmem_write(); - - pushExtValueFromMem(dreg, DSP_REG_AR3); - - increment_addr_reg(DSP_REG_AR3); - increment_addr_reg(DSP_REG_AR0); -} - -// SLN $acS.m, $axD.D -// xxxx xxxx 10dd 011s -// Store value from register $acS.m to memory location pointed by register -// $ar0. Load register $axD.D with value from memory pointed by register -// $ar3. Add corresponding indexing register $ix0 to addressing register $ar0 -// and increment $ar3. -void DSPEmitter::sln(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - dsp_op_read_reg(DSP_REG_AR0, RAX, ZERO); - get_acc_m(sreg, ECX, false); - dmem_write(); - - pushExtValueFromMem(dreg, DSP_REG_AR3); - - increment_addr_reg(DSP_REG_AR3); - increase_addr_reg(DSP_REG_AR0); -} - -// SLM $acS.m, $axD.D -// xxxx xxxx 10dd 101s -// Store value from register $acS.m to memory location pointed by register -// $ar0. Load register $axD.D with value from memory pointed by register -// $ar3. Add corresponding indexing register $ix3 to addressing register $ar3 -// and increment $ar0. -void DSPEmitter::slm(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - dsp_op_read_reg(DSP_REG_AR0, RAX, ZERO); - get_acc_m(sreg, ECX, false); - dmem_write(); - - pushExtValueFromMem(dreg, DSP_REG_AR3); - - increase_addr_reg(DSP_REG_AR3); - increment_addr_reg(DSP_REG_AR0); -} - -// SLMN $acS.m, $axD.D -// xxxx xxxx 10dd 111s -// Store value from register $acS.m to memory location pointed by register -// $ar0. Load register $axD.D with value from memory pointed by register -// $ar3. Add corresponding indexing register $ix0 to addressing register $ar0 -// and add corresponding indexing register $ix3 to addressing register $ar3. -void DSPEmitter::slnm(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1; - u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0; - dsp_op_read_reg(DSP_REG_AR0, RAX, ZERO); - get_acc_m(sreg, ECX, false); - dmem_write(); - - pushExtValueFromMem(dreg, DSP_REG_AR3); - - increase_addr_reg(DSP_REG_AR3); - increase_addr_reg(DSP_REG_AR0); -} - -// LD $ax0.d, $ax1.r, @$arS -// xxxx xxxx 11dr 00ss -// example for "nx'ld $AX0.L, $AX1.L, @$AR3" -// Loads the word pointed by AR0 to AX0.H, then loads the word pointed by AR3 -// to AX0.L. Increments AR0 and AR3. If AR0 and AR3 point into the same -// memory page (upper 6 bits of addr are the same -> games are not doing that!) -// then the value pointed by AR0 is loaded to BOTH AX0.H and AX0.L. If AR0 -// points into an invalid memory page (ie 0x2000), then AX0.H keeps its old -// value. (not implemented yet) If AR3 points into an invalid memory page, then -// AX0.L gets the same value as AX0.H. (not implemented yet) -void DSPEmitter::ld(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x1; - u8 rreg = (opc >> 4) & 0x1; - u8 sreg = opc & 0x3; - - if (sreg != DSP_REG_AR3) { - pushExtValueFromMem((dreg << 1) + DSP_REG_AXL0, sreg); - - // if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) { - dsp_op_read_reg(sreg, RSI, NONE); - dsp_op_read_reg(DSP_REG_AR3, RDI, NONE); - SHR(16, R(ESI), Imm8(10)); - SHR(16, R(EDI), Imm8(10)); - DSPJitRegCache c(gpr); - CMP(16, R(ESI), R(EDI)); - FixupBranch not_equal = J_CC(CC_NE,true); - pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg); - gpr.flushRegs(c); - FixupBranch after = J(true); - SetJumpTarget(not_equal); // else - pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3); - gpr.flushRegs(c); - SetJumpTarget(after); - - increment_addr_reg(sreg); - - } else { - pushExtValueFromMem(rreg + DSP_REG_AXH0, dreg); - - //if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) { - dsp_op_read_reg(dreg, RSI, NONE); - dsp_op_read_reg(DSP_REG_AR3, RDI, NONE); - SHR(16, R(ESI), Imm8(10)); - SHR(16, R(EDI), Imm8(10)); - DSPJitRegCache c(gpr); - CMP(16, R(ESI), R(EDI)); - FixupBranch not_equal = J_CC(CC_NE, true); - pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg); - gpr.flushRegs(c); - FixupBranch after = J(true); // else - SetJumpTarget(not_equal); - pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3); - gpr.flushRegs(c); - SetJumpTarget(after); - - increment_addr_reg(dreg); - } - - increment_addr_reg(DSP_REG_AR3); -} - -// LDN $ax0.d, $ax1.r, @$arS -// xxxx xxxx 11dr 01ss -void DSPEmitter::ldn(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x1; - u8 rreg = (opc >> 4) & 0x1; - u8 sreg = opc & 0x3; - - if (sreg != DSP_REG_AR3) { - pushExtValueFromMem((dreg << 1) + DSP_REG_AXL0, sreg); - - //if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) { - dsp_op_read_reg(sreg, RSI, NONE); - dsp_op_read_reg(DSP_REG_AR3, RDI, NONE); - SHR(16, R(ESI), Imm8(10)); - SHR(16, R(EDI), Imm8(10)); - DSPJitRegCache c(gpr); - CMP(16, R(ESI), R(EDI)); - FixupBranch not_equal = J_CC(CC_NE,true); - pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg); - gpr.flushRegs(c); - FixupBranch after = J(true); - SetJumpTarget(not_equal); // else - pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3); - gpr.flushRegs(c); - SetJumpTarget(after); - - increase_addr_reg(sreg); - } else { - pushExtValueFromMem(rreg + DSP_REG_AXH0, dreg); - - //if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) { - dsp_op_read_reg(dreg, RSI, NONE); - dsp_op_read_reg(DSP_REG_AR3, RDI, NONE); - SHR(16, R(ESI), Imm8(10)); - SHR(16, R(EDI), Imm8(10)); - DSPJitRegCache c(gpr); - CMP(16, R(ESI), R(EDI)); - FixupBranch not_equal = J_CC(CC_NE,true); - pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg); - gpr.flushRegs(c); - FixupBranch after = J(true); // else - SetJumpTarget(not_equal); - pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3); - gpr.flushRegs(c); - SetJumpTarget(after); - - increase_addr_reg(dreg); - } - - increment_addr_reg(DSP_REG_AR3); -} - -// LDM $ax0.d, $ax1.r, @$arS -// xxxx xxxx 11dr 10ss -void DSPEmitter::ldm(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x1; - u8 rreg = (opc >> 4) & 0x1; - u8 sreg = opc & 0x3; - - if (sreg != DSP_REG_AR3) { - pushExtValueFromMem((dreg << 1) + DSP_REG_AXL0, sreg); - - //if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) { - dsp_op_read_reg(sreg, RSI, NONE); - dsp_op_read_reg(DSP_REG_AR3, RDI, NONE); - SHR(16, R(ESI), Imm8(10)); - SHR(16, R(EDI), Imm8(10)); - DSPJitRegCache c(gpr); - CMP(16, R(ESI), R(EDI)); - FixupBranch not_equal = J_CC(CC_NE,true); - pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg); - gpr.flushRegs(c); - FixupBranch after = J(true); - SetJumpTarget(not_equal); // else - pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3); - gpr.flushRegs(c); - SetJumpTarget(after); - - increment_addr_reg(sreg); - } else { - pushExtValueFromMem(rreg + DSP_REG_AXH0, dreg); - - //if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) { - dsp_op_read_reg(dreg, RSI, NONE); - dsp_op_read_reg(DSP_REG_AR3, RDI, NONE); - SHR(16, R(ESI), Imm8(10)); - SHR(16, R(EDI), Imm8(10)); - DSPJitRegCache c(gpr); - CMP(16, R(ESI), R(EDI)); - FixupBranch not_equal = J_CC(CC_NE,true); - pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg); - gpr.flushRegs(c); - FixupBranch after = J(true); // else - SetJumpTarget(not_equal); - pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3); - gpr.flushRegs(c); - SetJumpTarget(after); - - increment_addr_reg(dreg); - } - - increase_addr_reg(DSP_REG_AR3); -} - -// LDNM $ax0.d, $ax1.r, @$arS -// xxxx xxxx 11dr 11ss -void DSPEmitter::ldnm(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x1; - u8 rreg = (opc >> 4) & 0x1; - u8 sreg = opc & 0x3; - - if (sreg != DSP_REG_AR3) { - pushExtValueFromMem((dreg << 1) + DSP_REG_AXL0, sreg); - - //if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) { - dsp_op_read_reg(sreg, RSI, NONE); - dsp_op_read_reg(DSP_REG_AR3, RDI, NONE); - SHR(16, R(ESI), Imm8(10)); - SHR(16, R(EDI), Imm8(10)); - DSPJitRegCache c(gpr); - CMP(16, R(ESI), R(EDI)); - FixupBranch not_equal = J_CC(CC_NE,true); - pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg); - gpr.flushRegs(c); - FixupBranch after = J(true); - SetJumpTarget(not_equal); // else - pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3); - gpr.flushRegs(c); - SetJumpTarget(after); - - increase_addr_reg(sreg); - } else { - pushExtValueFromMem(rreg + DSP_REG_AXH0, dreg); - - //if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) { - dsp_op_read_reg(dreg, RSI, NONE); - dsp_op_read_reg(DSP_REG_AR3, RDI, NONE); - SHR(16, R(ESI), Imm8(10)); - SHR(16, R(EDI), Imm8(10)); - DSPJitRegCache c(gpr); - CMP(16, R(ESI), R(EDI)); - FixupBranch not_equal = J_CC(CC_NE,true); - pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg); - gpr.flushRegs(c); - FixupBranch after = J(true); // else - SetJumpTarget(not_equal); - pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3); - gpr.flushRegs(c); - SetJumpTarget(after); - - increase_addr_reg(dreg); - } - - increase_addr_reg(DSP_REG_AR3); -} - - -// Push value from g_dsp.r[sreg] into EBX and stores the destinationindex in -// storeIndex -void DSPEmitter::pushExtValueFromReg(u16 dreg, u16 sreg) { - dsp_op_read_reg(sreg, RBX, ZERO); - storeIndex = dreg; -} - -void DSPEmitter::pushExtValueFromMem(u16 dreg, u16 sreg) { - // u16 addr = g_dsp.r[addr]; - dsp_op_read_reg(sreg, RCX, ZERO); - dmem_read(); - MOVZX(32, 16, EBX, R(EAX)); - - storeIndex = dreg; -} - -void DSPEmitter::pushExtValueFromMem2(u16 dreg, u16 sreg) { - // u16 addr = g_dsp.r[addr]; - dsp_op_read_reg(sreg, RCX, ZERO); - dmem_read(); - SHL(32, R(EAX), Imm8(16)); - OR(32, R(EBX), R(EAX)); - - storeIndex2 = dreg; -} - -void DSPEmitter::popExtValueToReg() { - // in practise, we rarely ever have a non-NX main op - // with an extended op, so the OR here is either - // not run (storeIndex == -1) or ends up OR'ing - // EBX with 0 (becoming the MOV we have here) - // nakee wants to keep it clean, so lets do that. - // [nakeee] the or case never happens in real - // [nakeee] it's just how the hardware works so we added it - if (storeIndex != -1) { - dsp_op_write_reg(storeIndex, RBX); - if (storeIndex >= DSP_REG_ACM0 && storeIndex2 == -1) { - TEST(32, R(EBX), Imm32(SR_40_MODE_BIT << 16)); - FixupBranch not_40bit = J_CC(CC_Z); - DSPJitRegCache c(gpr); - //if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT) - //{ - // Sign extend into whole accum. - //u16 val = g_dsp.r[reg]; - MOVSX(32, 16, EAX, R(EBX)); - SHR(32, R(EAX), Imm8(16)); - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000; - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0; - set_acc_h(storeIndex - DSP_REG_ACM0, R(RAX)); - set_acc_l(storeIndex - DSP_REG_ACM0, Imm16(0)); - //} - gpr.flushRegs(c); - SetJumpTarget(not_40bit); - } - } - - storeIndex = -1; - - if (storeIndex2 != -1) { - SHR(32, R(EBX), Imm8(16)); - dsp_op_write_reg(storeIndex2, RBX); - } - storeIndex2 = -1; -} - -// This function is being called in the main op after all input regs were read -// and before it writes into any regs. This way we can always use bitwise or to -// apply the ext command output, because if the main op didn't change the value -// then 0 | ext output = ext output and if it did then bitwise or is still the -// right thing to do -//this is only needed as long as we do fallback for ext ops -void DSPEmitter::zeroWriteBackLog(const UDSPInstruction opc) -{ - const DSPOPCTemplate *tinst = GetOpTemplate(opc); - - // Call extended - if (!tinst->extended) - return; - - if ((opc >> 12) == 0x3) { - if (! extOpTable[opc & 0x7F]->jitFunc) - { - SaveDSPRegs(); - ABI_CallFunction((void*)::zeroWriteBackLog); - LoadDSPRegs(); - } - } else { - if (! extOpTable[opc & 0xFF]->jitFunc) - { - SaveDSPRegs(); - ABI_CallFunction((void*)::zeroWriteBackLog); - LoadDSPRegs(); - } - } - return; -} diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitLoadStore.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitLoadStore.cpp deleted file mode 100644 index bd4a320bb3..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitLoadStore.cpp +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (C) 2003 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 "../DSPIntCCUtil.h" -#include "../DSPIntUtil.h" -#include "../DSPEmitter.h" -#include "DSPJitUtil.h" -#include "x64Emitter.h" -#include "ABI.h" -using namespace Gen; - -// 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 DSPEmitter::srs(const UDSPInstruction opc) -{ - u8 reg = ((opc >> 8) & 0x7) + 0x18; - //u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF); - dsp_op_read_reg(reg, RCX, ZERO); - dsp_op_read_reg(DSP_REG_CR, RAX, ZERO); - SHL(16, R(EAX), Imm8(8)); - OR(8, R(EAX), Imm8(opc & 0xFF)); - dmem_write(); -} - -// 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 DSPEmitter::lrs(const UDSPInstruction opc) -{ - u8 reg = ((opc >> 8) & 0x7) + 0x18; - //u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc & 0xFF); - dsp_op_read_reg(DSP_REG_CR, RCX, ZERO); - SHL(16, R(ECX), Imm8(8)); - OR(8, R(ECX), Imm8(opc & 0xFF)); - dmem_read(); - dsp_op_write_reg(reg, RAX); - dsp_conditional_extend_accum(reg); -} - -// 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 DSPEmitter::lr(const UDSPInstruction opc) -{ - int reg = opc & DSP_REG_MASK; - u16 address = dsp_imem_read(compilePC + 1); - dmem_read_imm(address); - dsp_op_write_reg(reg, EAX); - 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 DSPEmitter::sr(const UDSPInstruction opc) -{ - u8 reg = opc & DSP_REG_MASK; - u16 address = dsp_imem_read(compilePC + 1); - dsp_op_read_reg(reg, ECX); - dmem_write_imm(address); -} - -// 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 DSPEmitter::si(const UDSPInstruction opc) -{ - u16 address = (s8)opc; - u16 imm = dsp_imem_read(compilePC + 1); - MOV(32, R(ECX), Imm32((u32)imm)); - dmem_write_imm(address); -} - -// 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 DSPEmitter::lrr(const UDSPInstruction opc) -{ - u8 sreg = (opc >> 5) & 0x3; - u8 dreg = opc & 0x1f; - - dsp_op_read_reg(sreg, ECX); - dmem_read(); - dsp_op_write_reg(dreg, EAX); - dsp_conditional_extend_accum(dreg); -} - -// 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 DSPEmitter::lrrd(const UDSPInstruction opc) -{ - u8 sreg = (opc >> 5) & 0x3; - u8 dreg = opc & 0x1f; - - dsp_op_read_reg(sreg, ECX); - dmem_read(); - dsp_op_write_reg(dreg, EAX); - dsp_conditional_extend_accum(dreg); - 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 DSPEmitter::lrri(const UDSPInstruction opc) -{ - u8 sreg = (opc >> 5) & 0x3; - u8 dreg = opc & 0x1f; - - dsp_op_read_reg(sreg, ECX); - dmem_read(); - dsp_op_write_reg(dreg, EAX); - dsp_conditional_extend_accum(dreg); - 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 DSPEmitter::lrrn(const UDSPInstruction opc) -{ - u8 sreg = (opc >> 5) & 0x3; - u8 dreg = opc & 0x1f; - - dsp_op_read_reg(sreg, ECX); - dmem_read(); - dsp_op_write_reg(dreg, EAX); - dsp_conditional_extend_accum(dreg); - increase_addr_reg(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 DSPEmitter::srr(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x3; - u8 sreg = opc & 0x1f; - - dsp_op_read_reg(sreg, ECX); - dsp_op_read_reg(dreg, RAX, ZERO); - dmem_write(); -} - -// 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 DSPEmitter::srrd(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x3; - u8 sreg = opc & 0x1f; - - dsp_op_read_reg(sreg, ECX); - dsp_op_read_reg(dreg, RAX, ZERO); - dmem_write(); - 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 DSPEmitter::srri(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x3; - u8 sreg = opc & 0x1f; - - dsp_op_read_reg(sreg, ECX); - dsp_op_read_reg(dreg, RAX, ZERO); - dmem_write(); - 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 DSPEmitter::srrn(const UDSPInstruction opc) -{ - u8 dreg = (opc >> 5) & 0x3; - u8 sreg = opc & 0x1f; - - dsp_op_read_reg(sreg, ECX); - dsp_op_read_reg(dreg, RAX, ZERO); - dmem_write(); - increase_addr_reg(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 DSPEmitter::ilrr(const UDSPInstruction opc) -{ - u16 reg = opc & 0x3; - u16 dreg = (opc >> 8) & 1; - - dsp_op_read_reg(reg, RCX, ZERO); - imem_read(); - set_acc_m(dreg, R(RAX)); - dsp_conditional_extend_accum(dreg); -} - -// 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 DSPEmitter::ilrrd(const UDSPInstruction opc) -{ - u16 reg = opc & 0x3; - u16 dreg = (opc >> 8) & 1; - - dsp_op_read_reg(reg, RCX, ZERO); - imem_read(); - set_acc_m(dreg, R(RAX)); - dsp_conditional_extend_accum(dreg); - 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 DSPEmitter::ilrri(const UDSPInstruction opc) -{ - u16 reg = opc & 0x3; - u16 dreg = (opc >> 8) & 1; - - dsp_op_read_reg(reg, RCX, ZERO); - imem_read(); - set_acc_m(dreg, R(RAX)); - dsp_conditional_extend_accum(dreg); - 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 DSPEmitter::ilrrn(const UDSPInstruction opc) -{ - u16 reg = opc & 0x3; - u16 dreg = (opc >> 8) & 1; - - dsp_op_read_reg(reg, RCX, ZERO); - imem_read(); - set_acc_m(dreg, R(RAX)); - dsp_conditional_extend_accum(dreg); - increase_addr_reg(reg); -} - diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp deleted file mode 100644 index 2c8cc790de..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp +++ /dev/null @@ -1,468 +0,0 @@ -// Copyright (C) 2010 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 "../DSPIntUtil.h" -#include "../DSPEmitter.h" -#include "DSPJitUtil.h" -#include "x64Emitter.h" -#include "ABI.h" -using namespace Gen; - -//clobbers: -//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg] -//CX = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] -//expects: -//R11 = &g_dsp.r -void DSPEmitter::dsp_reg_stack_push(int stack_reg) -{ - //g_dsp.reg_stack_ptr[stack_reg]++; - //g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; -#ifdef _M_IX86 // All32 - MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg])); -#else - MOV(8, R(AL), MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg], - &g_dsp.r))); -#endif - ADD(8, R(AL), Imm8(1)); - AND(8, R(AL), Imm8(DSP_STACK_MASK)); -#ifdef _M_IX86 // All32 - MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL)); -#else - MOV(8, MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg], - &g_dsp.r)), R(AL)); -#endif - - //g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg]; -#ifdef _M_IX86 // All32 - MOV(16, R(CX), M(&g_dsp.r.st[stack_reg])); - MOVZX(32, 8, EAX, R(AL)); - MOV(16, MComplex(EAX, EAX, 1, (u32)&g_dsp.reg_stack[stack_reg][0]), R(CX)); -#else - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - MOV(16, R(CX), MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg]))); - MOVZX(64, 8, RAX, R(AL)); - MOV(16, MComplex(R11, RAX, 2, - PtrOffset(&g_dsp.reg_stack[stack_reg][0],&g_dsp.r)), - R(CX)); -#endif -} - -//clobbers: -//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg] -//CX = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] -//expects: -//R11 = &g_dsp.r -void DSPEmitter::dsp_reg_stack_pop(int stack_reg) -{ - //g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]; -#ifdef _M_IX86 // All32 - MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg])); -#else - MOV(8, R(AL), - MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg],&g_dsp.r))); -#endif -#ifdef _M_IX86 // All32 - MOVZX(32, 8, EAX, R(AL)); - MOV(16, R(CX), MComplex(EAX, EAX, 1, (u32)&g_dsp.reg_stack[stack_reg][0])); - MOV(16, M(&g_dsp.r.st[stack_reg]), R(CX)); -#else - MOVZX(64, 8, RAX, R(AL)); - MOV(16, R(CX), MComplex(R11, RAX, 2, - PtrOffset(&g_dsp.reg_stack[stack_reg][0], - &g_dsp.r))); - MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg])), R(CX)); -#endif - - //g_dsp.reg_stack_ptr[stack_reg]--; - //g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; - SUB(8, R(AL), Imm8(1)); - AND(8, R(AL), Imm8(DSP_STACK_MASK)); -#ifdef _M_IX86 // All32 - MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL)); -#else - MOV(8, MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg],&g_dsp.r)), - R(AL)); -#endif -} - - -void DSPEmitter::dsp_reg_store_stack(int stack_reg, Gen::X64Reg host_sreg) -{ - if (host_sreg != EDX) { - MOV(16, R(EDX), R(host_sreg)); - } - dsp_reg_stack_push(stack_reg); - //g_dsp.r[DSP_REG_ST0 + stack_reg] = val; -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.r.st[stack_reg]), R(EDX)); -#else - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg])), R(EDX)); -#endif -} - -void DSPEmitter::dsp_reg_load_stack(int stack_reg, Gen::X64Reg host_dreg) -{ - //u16 val = g_dsp.r[DSP_REG_ST0 + stack_reg]; -#ifdef _M_IX86 // All32 - MOV(16, R(EDX), M(&g_dsp.r.st[stack_reg])); -#else - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - MOV(16, R(EDX), MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg]))); -#endif - dsp_reg_stack_pop(stack_reg); - if (host_dreg != EDX) { - MOV(16, R(host_dreg), R(EDX)); - } -} - -void DSPEmitter::dsp_reg_store_stack_imm(int stack_reg, u16 val) -{ - dsp_reg_stack_push(stack_reg); - //g_dsp.r[DSP_REG_ST0 + stack_reg] = val; -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.r.st[stack_reg]), Imm16(val)); -#else - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg])), Imm16(val)); -#endif -} - -void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg) -{ - switch (reg & 0x1f) { - // 8-bit sign extended registers. - case DSP_REG_ACH0: - case DSP_REG_ACH1: - gpr.writeReg(reg, R(host_sreg)); - break; - - // Stack registers. - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - dsp_reg_store_stack(reg - DSP_REG_ST0, host_sreg); - break; - - default: - gpr.writeReg(reg, R(host_sreg)); - break; - } -} - -void DSPEmitter::dsp_op_write_reg_imm(int reg, u16 val) -{ - switch (reg & 0x1f) { - // 8-bit sign extended registers. Should look at prod.h too... - case DSP_REG_ACH0: - case DSP_REG_ACH1: - gpr.writeReg(reg, Imm16((u16)(s16)(s8)(u8)val)); - break; - // Stack registers. - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - dsp_reg_store_stack_imm(reg - DSP_REG_ST0, val); - break; - - default: - gpr.writeReg(reg, Imm16(val)); - break; - } -} - -void DSPEmitter::dsp_conditional_extend_accum(int reg) -{ - switch (reg) - { - case DSP_REG_ACM0: - case DSP_REG_ACM1: - { - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - DSPJitRegCache c(gpr); - TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); - FixupBranch not_40bit = J_CC(CC_Z,true); - //if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT) - //{ - // Sign extend into whole accum. - //u16 val = g_dsp.r[reg]; - get_acc_m(reg - DSP_REG_ACM0, EAX); - SHR(32, R(EAX), Imm8(16)); - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000; - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0; - set_acc_h(reg - DSP_REG_ACM0, R(RAX)); - set_acc_l(reg - DSP_REG_ACM0, Imm16(0)); - //} - gpr.flushRegs(c); - SetJumpTarget(not_40bit); - gpr.putReg(DSP_REG_SR); - } - } -} - -void DSPEmitter::dsp_conditional_extend_accum_imm(int reg, u16 val) -{ - switch (reg) - { - case DSP_REG_ACM0: - case DSP_REG_ACM1: - { - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - DSPJitRegCache c(gpr); - TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); - FixupBranch not_40bit = J_CC(CC_Z); - //if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT) - //{ - // Sign extend into whole accum. - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000; - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0; - set_acc_h(reg - DSP_REG_ACM0, Imm16((val & 0x8000)?0xffff:0x0000)); - set_acc_l(reg - DSP_REG_ACM0, Imm16(0)); - //} - gpr.flushRegs(c); - SetJumpTarget(not_40bit); - gpr.putReg(DSP_REG_SR); - } - } -} - -void DSPEmitter::dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend) -{ - switch (reg & 0x1f) { - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - dsp_reg_load_stack(reg - DSP_REG_ST0, host_dreg); - switch(extend) { - case SIGN: -#ifdef _M_IX86 // All32 - MOVSX(32, 16, host_dreg, R(host_dreg)); -#else - MOVSX(64, 16, host_dreg, R(host_dreg)); -#endif - break; - case ZERO: -#ifdef _M_IX86 // All32 - MOVZX(32, 16, host_dreg, R(host_dreg)); -#else - MOVZX(64, 16, host_dreg, R(host_dreg)); -#endif - break; - case NONE: - default: - break; - } - return; - default: - gpr.readReg(reg, host_dreg, extend); - return; - } -} - -// MRR $D, $S -// 0001 11dd ddds ssss -// Move value from register $S to register $D. -// FIXME: Perform additional operation depending on destination register. -void DSPEmitter::mrr(const UDSPInstruction opc) -{ - u8 sreg = opc & 0x1f; - u8 dreg = (opc >> 5) & 0x1f; - - dsp_op_read_reg(sreg, EDX); - dsp_op_write_reg(dreg, EDX); - dsp_conditional_extend_accum(dreg); -} - -// LRI $D, #I -// 0000 0000 100d dddd -// iiii iiii iiii iiii -// Load immediate value I to register $D. -// -// 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 DSPEmitter::lri(const UDSPInstruction opc) -{ - u8 reg = opc & DSP_REG_MASK; - u16 imm = dsp_imem_read(compilePC+1); - dsp_op_write_reg_imm(reg, imm); - dsp_conditional_extend_accum_imm(reg, imm); -} - -// 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 DSPEmitter::lris(const UDSPInstruction opc) -{ - u8 reg = ((opc >> 8) & 0x7) + DSP_REG_AXL0; - u16 imm = (s8)opc; - dsp_op_write_reg_imm(reg, imm); - dsp_conditional_extend_accum_imm(reg, imm); -} - -//---- - -// NX -// 1000 -000 xxxx xxxx -// No operation, but can be extended with extended opcode. -// 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. -void DSPEmitter::nx(const UDSPInstruction opc) -{ - zeroWriteBackLog(opc); -} - -//---- - -// DAR $arD -// 0000 0000 0000 01dd -// Decrement address register $arD. -void DSPEmitter::dar(const UDSPInstruction opc) -{ - // g_dsp.r[opc & 0x3] = dsp_decrement_addr_reg(opc & 0x3); - decrement_addr_reg(opc & 0x3); - -} - -// IAR $arD -// 0000 0000 0000 10dd -// Increment address register $arD. -void DSPEmitter::iar(const UDSPInstruction opc) -{ - // g_dsp.r[opc & 0x3] = dsp_increment_addr_reg(opc & 0x3); - increment_addr_reg(opc & 0x3); -} - -// SUBARN $arD -// 0000 0000 0000 11dd -// Subtract indexing register $ixD from an addressing register $arD. -// used only in IPL-NTSC ucode -void DSPEmitter::subarn(const UDSPInstruction opc) -{ - // u8 dreg = opc & 0x3; - // g_dsp.r[dreg] = dsp_decrease_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]); - decrease_addr_reg(opc & 0x3); -} - -// ADDARN $arD, $ixS -// 0000 0000 0001 ssdd -// Adds indexing register $ixS to an addressing register $arD. -// It is critical for the Zelda ucode that this one wraps correctly. -void DSPEmitter::addarn(const UDSPInstruction opc) -{ - // u8 dreg = opc & 0x3; - // u8 sreg = (opc >> 2) & 0x3; - // g_dsp.r[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]); - - // From looking around it is always called with the matching index register - increase_addr_reg(opc & 0x3); -} - -//---- - - -void DSPEmitter::setCompileSR(u16 bit) { - - // g_dsp.r[DSP_REG_SR] |= bit - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - OR(16, sr_reg, Imm16(bit)); - gpr.putReg(DSP_REG_SR); - - compileSR |= bit; -} - -void DSPEmitter::clrCompileSR(u16 bit) { - - // g_dsp.r[DSP_REG_SR] &= bit - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - AND(16, sr_reg, Imm16(~bit)); - gpr.putReg(DSP_REG_SR); - - compileSR &= ~bit; -} -// SBCLR #I -// 0001 0011 aaaa aiii -// bit of status register $sr. Bit number is calculated by adding 6 to -// immediate value I. -void DSPEmitter::sbclr(const UDSPInstruction opc) -{ - u8 bit = (opc & 0x7) + 6; - - clrCompileSR(1 << bit); -} - -// SBSET #I -// 0001 0010 aaaa aiii -// Set bit of status register $sr. Bit number is calculated by adding 6 to -// immediate value I. -void DSPEmitter::sbset(const UDSPInstruction opc) -{ - u8 bit = (opc & 0x7) + 6; - - setCompileSR(1 << bit); -} - -// 1000 1bbb xxxx xxxx, bbb >= 010 -// 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. -void DSPEmitter::srbith(const UDSPInstruction opc) -{ - zeroWriteBackLog(opc); - switch ((opc >> 8) & 0xf) - { - // M0/M2 change the multiplier mode (it can multiply by 2 for free). - case 0xa: // M2 - clrCompileSR(SR_MUL_MODIFY); - break; - case 0xb: // M0 - setCompileSR(SR_MUL_MODIFY); - break; - - // If set, treat multiplicands as unsigned. - // If clear, treat them as signed. - case 0xc: // CLR15 - clrCompileSR(SR_MUL_UNSIGNED); - break; - case 0xd: // SET15 - setCompileSR(SR_MUL_UNSIGNED); - break; - - // Automatic 40-bit sign extension when loading ACx.M. - // SET40 changes something very important: see the LRI instruction above. - case 0xe: // SET16 (CLR40) - clrCompileSR(SR_40_MODE_BIT); - break; - - case 0xf: // SET40 - setCompileSR(SR_40_MODE_BIT); - break; - - default: - break; - } -} - diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitMultiplier.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitMultiplier.cpp deleted file mode 100644 index 0004b33396..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitMultiplier.cpp +++ /dev/null @@ -1,885 +0,0 @@ -// Copyright (C) 2003 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 - - -// Multiplier and product register control - -#include "../DSPIntUtil.h" -#include "../DSPEmitter.h" -#include "../DSPAnalyzer.h" -#ifdef _M_X64 -#include "DSPJitUtil.h" -#endif -#include "x64Emitter.h" -#include "ABI.h" -using namespace Gen; - -// Returns s64 in RAX -// In: RSI = s16 a, RDI = s16 b -void DSPEmitter::multiply() -{ -#ifdef _M_X64 -// prod = (s16)a * (s16)b; //signed - MOV(64, R(EAX), R(RDI)); - IMUL(64, R(ESI)); - -// Conditionally multiply by 2. -// if ((g_dsp.r.sr & SR_MUL_MODIFY) == 0) - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - TEST(16, sr_reg, Imm16(SR_MUL_MODIFY)); - FixupBranch noMult2 = J_CC(CC_NZ); -// prod <<= 1; - SHL(64, R(EAX), Imm8(1)); - SetJumpTarget(noMult2); - gpr.putReg(DSP_REG_SR); -// return prod; -#endif -} - -// Returns s64 in RAX -// Clobbers RDX -void DSPEmitter::multiply_add() -{ -// s64 prod = dsp_get_long_prod() + dsp_get_multiply_prod(a, b, sign); - multiply(); - MOV(64, R(RDX), R(RAX)); - get_long_prod(); - ADD(64, R(RAX), R(RDX)); -// return prod; -} - -// Returns s64 in RAX -// Clobbers RDX -void DSPEmitter::multiply_sub() -{ -// s64 prod = dsp_get_long_prod() - dsp_get_multiply_prod(a, b, sign); - multiply(); - MOV(64, R(RDX), R(RAX)); - get_long_prod(); - SUB(64, R(RAX), R(RDX)); -// return prod; -} - -// Only MULX family instructions have unsigned/mixed support. -// Returns s64 in EAX -// In: RSI = s16 a, RDI = s16 b -// Returns s64 in RAX -void DSPEmitter::multiply_mulx(u8 axh0, u8 axh1) -{ -// s64 result; - -// if ((axh0==0) && (axh1==0)) -// result = dsp_multiply(val1, val2, 1); // unsigned support ON if both ax?.l regs are used -// else if ((axh0==0) && (axh1==1)) -// result = dsp_multiply(val1, val2, 2); // mixed support ON (u16)axl.0 * (s16)axh.1 -// else if ((axh0==1) && (axh1==0)) -// result = dsp_multiply(val2, val1, 2); // mixed support ON (u16)axl.1 * (s16)axh.0 -// else -// result = dsp_multiply(val1, val2, 0); // unsigned support OFF if both ax?.h regs are used - - -// if ((sign == 1) && (g_dsp.r.sr & SR_MUL_UNSIGNED)) //unsigned - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - TEST(16, sr_reg, Imm16(SR_MUL_UNSIGNED)); - FixupBranch unsignedMul = J_CC(CC_NZ); - // prod = (s16)a * (s16)b; //signed - MOVSX(64, 16, RAX, R(RDI)); - IMUL(64, R(RSI)); - FixupBranch signedMul = J(); - - SetJumpTarget(unsignedMul); - if ((axh0==0) && (axh1==0)) - { - // unsigned support ON if both ax?.l regs are used -// prod = (u32)(a * b); - MOVZX(64, 16, RSI, R(RSI)); - MOVZX(64, 16, RAX, R(RDI)); - MUL(64, R(RSI)); - } - else if ((axh0==0) && (axh1==1)) - { - // mixed support ON (u16)axl.0 * (s16)axh.1 -// prod = a * (s16)b; - MOVZX(64, 16, RAX, R(RSI)); - IMUL(64, R(RDI)); - } - else if ((axh0==1) && (axh1==0)) - { - // mixed support ON (u16)axl.1 * (s16)axh.0 -// prod = (s16)a * b; - MOVZX(64, 16, RAX, R(RDI)); - IMUL(64, R(RSI)); - } - else - { - // unsigned support OFF if both ax?.h regs are used -// prod = (s16)a * (s16)b; //signed - MOVSX(64, 16, RAX, R(RDI)); - IMUL(64, R(RSI)); - } - - SetJumpTarget(signedMul); - - // Conditionally multiply by 2. -// if ((g_dsp.r.sr & SR_MUL_MODIFY) == 0) - TEST(16, sr_reg, Imm16(SR_MUL_MODIFY)); - FixupBranch noMult2 = J_CC(CC_NZ); -// prod <<= 1; - SHL(64, R(RAX), Imm8(1)); - SetJumpTarget(noMult2); - gpr.putReg(DSP_REG_SR); -// return prod; -} - -//---- - -// CLRP -// 1000 0100 xxxx xxxx -// Clears product register $prod. -// Magic numbers taken from duddie's doc - -// 00ff_(fff0 + 0010)_0000 = 0100_0000_0000, conveniently, lower 40bits = 0 - -// It's not ok, to just zero all of them, correct values should be set because of -// direct use of prod regs by AX/AXWII (look @that part of ucode). -void DSPEmitter::clrp(const UDSPInstruction opc) -{ -#ifdef _M_X64 -// g_dsp.r[DSP_REG_PRODL] = 0x0000; -// g_dsp.r[DSP_REG_PRODM] = 0xfff0; -// g_dsp.r[DSP_REG_PRODH] = 0x00ff; -// g_dsp.r[DSP_REG_PRODM2] = 0x0010; - //64bit move to memory does not work. use 2 32bits - MOV(32, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.val)+0), Imm32(0xfff00000U)); - MOV(32, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.val)+4), Imm32(0x001000ffU)); -#else - Default(opc); -#endif -} - -// TSTPROD -// 1000 0101 xxxx xxxx -// Test prod regs value. - -// flags out: --xx xx0x -void DSPEmitter::tstprod(const UDSPInstruction opc) -{ -#ifdef _M_X64 - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { -// s64 prod = dsp_get_long_prod(); - get_long_prod(); -// Update_SR_Register64(prod); - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -//---- - -// MOVP $acD -// 0110 111d xxxx xxxx -// Moves multiply product from $prod register to accumulator $acD register. - -// flags out: --xx xx0x -void DSPEmitter::movp(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - -// s64 acc = dsp_get_long_prod(); - get_long_prod(); -// dsp_set_long_acc(dreg, acc); - set_long_acc(dreg); -// Update_SR_Register64(acc); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// MOVNP $acD -// 0111 111d xxxx xxxx -// Moves negative of multiply product from $prod register to accumulator -// $acD register. - -// flags out: --xx xx0x -void DSPEmitter::movnp(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - -// s64 acc = -dsp_get_long_prod(); - get_long_prod(); - NEG(64, R(EAX)); -// dsp_set_long_acc(dreg, acc); - set_long_acc(dreg); -// Update_SR_Register64(acc); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// MOVPZ $acD -// 1111 111d xxxx xxxx -// Moves multiply product from $prod register to accumulator $acD -// register and sets (rounds) $acD.l to 0 - -// flags out: --xx xx0x -void DSPEmitter::movpz(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x01; - -// s64 acc = dsp_get_long_prod_round_prodl(); - get_long_prod_round_prodl(); -// dsp_set_long_acc(dreg, acc); - set_long_acc(dreg); -// Update_SR_Register64(acc); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// ADDPAXZ $acD, $axS -// 1111 10sd xxxx xxxx -// Adds secondary accumulator $axS to product register and stores result -// in accumulator register. Low 16-bits of $acD ($acD.l) are set (round) to 0. - -// flags out: --xx xx0x -void DSPEmitter::addpaxz(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 dreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - -// s64 ax = dsp_get_long_acx(sreg); - get_long_acx(sreg, RCX); - MOV(64, R(RDI), R(RCX)); -// s64 res = prod + (ax & ~0xffff); - MOV(64, R(RDX), Imm64(~0xffff)); - AND(64, R(RDI), R(RDX)); -// s64 prod = dsp_get_long_prod_round_prodl(); - get_long_prod_round_prodl(); - ADD(64, R(RAX), R(RDI)); - -// s64 oldprod = dsp_get_long_prod(); -// dsp_set_long_acc(dreg, res); -// res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry(oldprod, res), false); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - get_long_prod(RDX); - MOV(64, R(RSI), R(RAX)); - set_long_acc(dreg, RSI); - Update_SR_Register64_Carry(); - } - else - { - set_long_acc(dreg, RAX); - } -#else - Default(opc); -#endif -} - -//---- - -// MULAXH -// 1000 0011 xxxx xxxx -// Multiply $ax0.h by $ax0.h -void DSPEmitter::mulaxh(const UDSPInstruction opc) -{ -#ifdef _M_X64 -// s64 prod = dsp_multiply(dsp_get_ax_h(0), dsp_get_ax_h(0)); - dsp_op_read_reg(DSP_REG_AXH0, RSI, SIGN); - MOV(64, R(RDI), R(RSI)); - multiply(); -// dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} - -//---- - -// MUL $axS.l, $axS.h -// 1001 s000 xxxx xxxx -// Multiply low part $axS.l of secondary accumulator $axS by high part -// $axS.h of secondary accumulator $axS (treat them both as signed). -void DSPEmitter::mul(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 sreg = (opc >> 11) & 0x1; - -// u16 axl = dsp_get_ax_l(sreg); - dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN); -// u16 axh = dsp_get_ax_h(sreg); - dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN); -// s64 prod = dsp_multiply(axh, axl); - multiply(); -// dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} - -// MULAC $axS.l, $axS.h, $acR -// 1001 s10r xxxx xxxx -// Add product register to accumulator register $acR. Multiply low part -// $axS.l of secondary accumulator $axS by high part $axS.h of secondary -// accumulator $axS (treat them both as signed). - -// flags out: --xx xx0x -void DSPEmitter::mulac(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 11) & 0x1; - -// s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod(); - get_long_acc(rreg); - MOV(64, R(RDX), R(RAX)); - get_long_prod(); - ADD(64, R(RAX), R(RDX)); - PUSH(64, R(RAX)); -// u16 axl = dsp_get_ax_l(sreg); - dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN); -// u16 axh = dsp_get_ax_h(sreg); - dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN); -// s64 prod = dsp_multiply(axl, axh); - multiply(); -// dsp_set_long_prod(prod); - set_long_prod(); -// dsp_set_long_acc(rreg, acc); - POP(64, R(RAX)); - set_long_acc(rreg); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// MULMV $axS.l, $axS.h, $acR -// 1001 s11r xxxx xxxx -// Move product register to accumulator register $acR. Multiply low part -// $axS.l of secondary accumulator $axS by high part $axS.h of secondary -// accumulator $axS (treat them both as signed). - -// flags out: --xx xx0x -void DSPEmitter::mulmv(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x1; - -// s64 acc = dsp_get_long_prod(); - get_long_prod(); - PUSH(64, R(RAX)); - mul(opc); -// dsp_set_long_acc(rreg, acc); - POP(64, R(RAX)); - set_long_acc(rreg); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// MULMVZ $axS.l, $axS.h, $acR -// 1001 s01r xxxx xxxx -// Move product register to accumulator register $acR and clear (round) low part -// of accumulator register $acR.l. Multiply low part $axS.l of secondary -// accumulator $axS by high part $axS.h of secondary accumulator $axS (treat -// them both as signed). - -// flags out: --xx xx0x -void DSPEmitter::mulmvz(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x1; - -// s64 acc = dsp_get_long_prod_round_prodl(); - get_long_prod_round_prodl(RDX); -// dsp_set_long_acc(rreg, acc); - set_long_acc(rreg, RDX); - mul(opc); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RDX); - } -#else - Default(opc); -#endif -} - -//---- - -// MULX $ax0.S, $ax1.T -// 101s t000 xxxx xxxx -// Multiply one part $ax0 by one part $ax1. -// Part is selected by S and T bits. Zero selects low part, one selects high part. -void DSPEmitter::mulx(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 treg = ((opc >> 11) & 0x1); - u8 sreg = ((opc >> 12) & 0x1); - - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); -// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN); -// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN); -// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); - multiply_mulx(sreg, treg); -// dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} - -// MULXAC $ax0.S, $ax1.T, $acR -// 101s t01r xxxx xxxx -// Add product register to accumulator register $acR. Multiply one part -// $ax0 by one part $ax1. Part is selected by S and -// T bits. Zero selects low part, one selects high part. - -// flags out: --xx xx0x -void DSPEmitter::mulxac(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - -// s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod(); - get_long_acc(rreg, RCX); - get_long_prod(); - ADD(64, R(RCX), R(RAX)); -// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN); -// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN); -// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); - multiply_mulx(sreg, treg); - -// dsp_set_long_prod(prod); - set_long_prod(); -// dsp_set_long_acc(rreg, acc); - set_long_acc(rreg, RCX); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RCX); - } -#else - Default(opc); -#endif -} - -// MULXMV $ax0.S, $ax1.T, $acR -// 101s t11r xxxx xxxx -// Move product register to accumulator register $acR. Multiply one part -// $ax0 by one part $ax1. Part is selected by S and -// T bits. Zero selects low part, one selects high part. - -// flags out: --xx xx0x -void DSPEmitter::mulxmv(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = ((opc >> 8) & 0x1); - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - -// s64 acc = dsp_get_long_prod(); - get_long_prod(RCX); -// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN); -// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN); -// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); - multiply_mulx(sreg, treg); - -// dsp_set_long_prod(prod); - set_long_prod(); -// dsp_set_long_acc(rreg, acc); - set_long_acc(rreg, RCX); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RCX); - } -#else - Default(opc); -#endif -} - -// MULXMV $ax0.S, $ax1.T, $acR -// 101s t01r xxxx xxxx -// Move product register to accumulator register $acR and clear (round) low part -// of accumulator register $acR.l. Multiply one part $ax0 by one part $ax1 -// Part is selected by S and T bits. Zero selects low part, -// one selects high part. - -// flags out: --xx xx0x -void DSPEmitter::mulxmvz(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - -// s64 acc = dsp_get_long_prod_round_prodl(); - get_long_prod_round_prodl(RCX); -// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN); -// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN); -// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2); - multiply_mulx(sreg, treg); - -// dsp_set_long_prod(prod); - set_long_prod(); -// dsp_set_long_acc(rreg, acc); - set_long_acc(rreg, RCX); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(RCX); - } -#else - Default(opc); -#endif -} - -//---- - -// MULC $acS.m, $axT.h -// 110s t000 xxxx xxxx -// Multiply mid part of accumulator register $acS.m by high part $axS.h of -// secondary accumulator $axS (treat them both as signed). -void DSPEmitter::mulc(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - -// u16 accm = dsp_get_acc_m(sreg); - get_acc_m(sreg, ESI); -// u16 axh = dsp_get_ax_h(treg); - dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN); -// s64 prod = dsp_multiply(accm, axh); - multiply(); -// dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} - -// MULCAC $acS.m, $axT.h, $acR -// 110s t10r xxxx xxxx -// Multiply mid part of accumulator register $acS.m by high part $axS.h of -// secondary accumulator $axS (treat them both as signed). Add product -// register before multiplication to accumulator $acR. - -// flags out: --xx xx0x -void DSPEmitter::mulcac(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - -// s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod(); - get_long_acc(rreg); - MOV(64, R(RDX), R(RAX)); - get_long_prod(); - ADD(64, R(RAX), R(RDX)); - PUSH(64, R(RAX)); -// u16 accm = dsp_get_acc_m(sreg); - get_acc_m(sreg, ESI); -// u16 axh = dsp_get_ax_h(treg); - dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN); -// s64 prod = dsp_multiply(accm, axh); - multiply(); -// dsp_set_long_prod(prod); - set_long_prod(); -// dsp_set_long_acc(rreg, acc); - POP(64, R(RAX)); - set_long_acc(rreg); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// MULCMV $acS.m, $axT.h, $acR -// 110s t11r xxxx xxxx -// Multiply mid part of accumulator register $acS.m by high part $axT.h of -// secondary accumulator $axT (treat them both as signed). Move product -// register before multiplication to accumulator $acR. -// possible mistake in duddie's doc axT.h rather than axS.h - -// flags out: --xx xx0x -void DSPEmitter::mulcmv(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - -// s64 acc = dsp_get_long_prod(); - get_long_prod(); - PUSH(64, R(RAX)); -// u16 accm = dsp_get_acc_m(sreg); - get_acc_m(sreg, ESI); -// u16 axh = dsp_get_ax_h(treg); - dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN); -// s64 prod = dsp_multiply(accm, axh); - multiply(); -// dsp_set_long_prod(prod); - set_long_prod(); -// dsp_set_long_acc(rreg, acc); - POP(64, R(RAX)); - set_long_acc(rreg); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -// MULCMVZ $acS.m, $axT.h, $acR -// 110s t01r xxxx xxxx -// (fixed possible bug in duddie's description, s->t) -// Multiply mid part of accumulator register $acS.m by high part $axT.h of -// secondary accumulator $axT (treat them both as signed). Move product -// register before multiplication to accumulator $acR, set (round) low part of -// accumulator $acR.l to zero. - -// flags out: --xx xx0x -void DSPEmitter::mulcmvz(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 rreg = (opc >> 8) & 0x1; - u8 treg = (opc >> 11) & 0x1; - u8 sreg = (opc >> 12) & 0x1; - - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); -// s64 acc = dsp_get_long_prod_round_prodl(); - get_long_prod_round_prodl(); - PUSH(64, R(RAX)); -// u16 accm = dsp_get_acc_m(sreg); - get_acc_m(sreg, ESI); -// u16 axh = dsp_get_ax_h(treg); - dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN); -// s64 prod = dsp_multiply(accm, axh); - multiply(); -// dsp_set_long_prod(prod); - set_long_prod(); -// dsp_set_long_acc(rreg, acc); - POP(64, R(RAX)); - set_long_acc(rreg); -// Update_SR_Register64(dsp_get_long_acc(rreg)); - if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR)) - { - Update_SR_Register64(); - } -#else - Default(opc); -#endif -} - -//---- - -// MADDX ax0.S ax1.T -// 1110 00st xxxx xxxx -// Multiply one part of secondary accumulator $ax0 (selected by S) by -// one part of secondary accumulator $ax1 (selected by T) (treat them both as -// signed) and add result to product register. -void DSPEmitter::maddx(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 treg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - // u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN); - // u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN); - // s64 prod = dsp_multiply_add(val1, val2); - multiply_add(); - // dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} - -// MSUBX $(0x18+S*2), $(0x19+T*2) -// 1110 01st xxxx xxxx -// Multiply one part of secondary accumulator $ax0 (selected by S) by -// one part of secondary accumulator $ax1 (selected by T) (treat them both as -// signed) and subtract result from product register. -void DSPEmitter::msubx(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 treg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - - // u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0); - dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN); - // u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1); - dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN); - // s64 prod = dsp_multiply_sub(val1, val2); - multiply_sub(); - // dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} - -// MADDC $acS.m, $axT.h -// 1110 10st xxxx xxxx -// Multiply middle part of accumulator $acS.m by high part of secondary -// accumulator $axT.h (treat them both as signed) and add result to product -// register. -void DSPEmitter::maddc(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 treg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - -// u16 accm = dsp_get_acc_m(sreg); - get_acc_m(sreg, ESI); -// u16 axh = dsp_get_ax_h(treg); - dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN); -// s64 prod = dsp_multiply_add(accm, axh); - multiply_add(); -// dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} - -// MSUBC $acS.m, $axT.h -// 1110 11st xxxx xxxx -// Multiply middle part of accumulator $acS.m by high part of secondary -// accumulator $axT.h (treat them both as signed) and subtract result from -// product register. -void DSPEmitter::msubc(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 treg = (opc >> 8) & 0x1; - u8 sreg = (opc >> 9) & 0x1; - -// u16 accm = dsp_get_acc_m(sreg); - get_acc_m(sreg, ESI); -// u16 axh = dsp_get_ax_h(treg); - dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN); -// s64 prod = dsp_multiply_sub(accm, axh); - multiply_sub(); -// dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} - -// MADD $axS.l, $axS.h -// 1111 001s xxxx xxxx -// Multiply low part $axS.l of secondary accumulator $axS by high part -// $axS.h of secondary accumulator $axS (treat them both as signed) and add -// result to product register. -void DSPEmitter::madd(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 sreg = (opc >> 8) & 0x1; - -// u16 axl = dsp_get_ax_l(sreg); - dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN); -// u16 axh = dsp_get_ax_h(sreg); - dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN); -// s64 prod = dsp_multiply_add(axl, axh); - multiply_add(); -// dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} - -// MSUB $axS.l, $axS.h -// 1111 011s xxxx xxxx -// Multiply low part $axS.l of secondary accumulator $axS by high part -// $axS.h of secondary accumulator $axS (treat them both as signed) and -// subtract result from product register. -void DSPEmitter::msub(const UDSPInstruction opc) -{ -#ifdef _M_X64 - u8 sreg = (opc >> 8) & 0x1; - -// u16 axl = dsp_get_ax_l(sreg); - dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN); -// u16 axh = dsp_get_ax_h(sreg); - dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN); -// s64 prod = dsp_multiply_sub(axl, axh); - multiply_sub(); -// dsp_set_long_prod(prod); - set_long_prod(); -#else - Default(opc); -#endif -} diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitRegCache.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitRegCache.cpp deleted file mode 100644 index 5a08db1982..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitRegCache.cpp +++ /dev/null @@ -1,540 +0,0 @@ -// Copyright (C) 2011 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 "DSPJitRegCache.h" -#include "../DSPEmitter.h" -#include "../DSPMemoryMap.h" - -using namespace Gen; - -static u16 *reg_ptr(int reg) { - switch(reg) { - case DSP_REG_AR0: - case DSP_REG_AR1: - case DSP_REG_AR2: - case DSP_REG_AR3: - return &g_dsp.r.ar[reg - DSP_REG_AR0]; - case DSP_REG_IX0: - case DSP_REG_IX1: - case DSP_REG_IX2: - case DSP_REG_IX3: - return &g_dsp.r.ix[reg - DSP_REG_IX0]; - case DSP_REG_WR0: - case DSP_REG_WR1: - case DSP_REG_WR2: - case DSP_REG_WR3: - return &g_dsp.r.wr[reg - DSP_REG_WR0]; - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - return &g_dsp.r.st[reg - DSP_REG_ST0]; - case DSP_REG_ACH0: - case DSP_REG_ACH1: - return &g_dsp.r.ac[reg - DSP_REG_ACH0].h; - case DSP_REG_CR: return &g_dsp.r.cr; - case DSP_REG_SR: return &g_dsp.r.sr; - case DSP_REG_PRODL: return &g_dsp.r.prod.l; - case DSP_REG_PRODM: return &g_dsp.r.prod.m; - case DSP_REG_PRODH: return &g_dsp.r.prod.h; - case DSP_REG_PRODM2: return &g_dsp.r.prod.m2; - case DSP_REG_AXL0: - case DSP_REG_AXL1: - return &g_dsp.r.ax[reg - DSP_REG_AXL0].l; - case DSP_REG_AXH0: - case DSP_REG_AXH1: - return &g_dsp.r.ax[reg - DSP_REG_AXH0].h; - case DSP_REG_ACL0: - case DSP_REG_ACL1: - return &g_dsp.r.ac[reg - DSP_REG_ACL0].l; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - return &g_dsp.r.ac[reg - DSP_REG_ACM0].m; - default: - _assert_msg_(DSPLLE, 0, "cannot happen"); - return NULL; - } -} - -#define ROTATED_REG_ACCS -//#undef ROTATED_REG_ACCS - -DSPJitRegCache::DSPJitRegCache(DSPEmitter &_emitter) - : emitter(_emitter), temporary(false), merged(false) { - for(unsigned int i = 0; i < NUMXREGS; i++) { - xregs[i].guest_reg = DSP_REG_STATIC; - } - xregs[RSP].guest_reg = DSP_REG_STATIC;//stack pointer - xregs[RBX].guest_reg = DSP_REG_STATIC;//extended op backing store - - xregs[RBP].guest_reg = DSP_REG_NONE;//definitely usable in dsplle because - //all external calls are protected - -#ifdef _M_X64 - xregs[R8].guest_reg = DSP_REG_STATIC;//acc0 - xregs[R9].guest_reg = DSP_REG_STATIC;//acc1 - xregs[R10].guest_reg = DSP_REG_NONE; - xregs[R11].guest_reg = DSP_REG_STATIC;//&g_dsp.r - xregs[R12].guest_reg = DSP_REG_STATIC;//used for cycle counting - xregs[R13].guest_reg = DSP_REG_NONE; - xregs[R14].guest_reg = DSP_REG_NONE; - xregs[R15].guest_reg = DSP_REG_NONE; -#endif - -#ifdef _M_X64 - acc[0].host_reg = R8; - acc[0].shift = 0; - acc[0].dirty = false; - acc[0].used = false; - acc[0].tmp_reg = INVALID_REG; - - acc[1].host_reg = R9; - acc[1].shift = 0; - acc[1].dirty = false; - acc[1].used = false; - acc[1].tmp_reg = INVALID_REG; -#endif - for(unsigned int i = 0; i < 32; i++) { - regs[i].mem = reg_ptr(i); - regs[i].size = 2; - } -#ifdef _M_X64 - regs[DSP_REG_ACC0_64].mem = &g_dsp.r.ac[0].val; - regs[DSP_REG_ACC0_64].size = 8; - regs[DSP_REG_ACC1_64].mem = &g_dsp.r.ac[1].val; - regs[DSP_REG_ACC1_64].size = 8; - regs[DSP_REG_PROD_64].mem = &g_dsp.r.prod.val; - regs[DSP_REG_PROD_64].size = 8; -#endif - regs[DSP_REG_AX0_32].mem = &g_dsp.r.ax[0].val; - regs[DSP_REG_AX0_32].size = 4; - regs[DSP_REG_AX1_32].mem = &g_dsp.r.ax[1].val; - regs[DSP_REG_AX1_32].size = 4; - for(unsigned int i = 0; i < DSP_REG_MAX_MEM_BACKED+1; i++) { - regs[i].dirty = false; -#ifdef _M_IX86 // All32 - regs[i].loc = M(regs[i].mem); -#else - regs[i].loc = MDisp(R11, PtrOffset(regs[i].mem, &g_dsp.r)); -#endif - } -} - -DSPJitRegCache::DSPJitRegCache(const DSPJitRegCache &cache) - : emitter(cache.emitter), temporary(true), merged(false) -{ - memcpy(xregs,cache.xregs,sizeof(xregs)); -#ifdef _M_X64 - memcpy(acc,cache.acc,sizeof(acc)); -#endif - memcpy(regs,cache.regs,sizeof(regs)); -} - -DSPJitRegCache& DSPJitRegCache::operator=(const DSPJitRegCache &cache) -{ - _assert_msg_(DSPLLE, &emitter == &cache.emitter, "emitter does not match"); - _assert_msg_(DSPLLE, temporary, "register cache not temporary??"); - merged = false; - memcpy(xregs,cache.xregs,sizeof(xregs)); -#ifdef _M_X64 - memcpy(acc,cache.acc,sizeof(acc)); -#endif - memcpy(regs,cache.regs,sizeof(regs)); - - return *this; -} - -DSPJitRegCache::~DSPJitRegCache() -{ - _assert_msg_(DSPLLE, !temporary || merged, "temporary cache not merged"); -} - -void DSPJitRegCache::flushRegs(DSPJitRegCache &cache, bool emit) -{ - cache.merged = true; - -#ifdef _M_X64 - for(unsigned int i = 0; i < 2; i++) { - if (acc[i].shift > cache.acc[i].shift) { - if (emit) - emitter.ROL(64, R(acc[i].host_reg), - Imm8(acc[i].shift-cache.acc[i].shift)); - acc[i].shift = cache.acc[i].shift; - } - if (acc[i].shift < cache.acc[i].shift) { - if (emit) - emitter.ROR(64, R(acc[i].host_reg), - Imm8(cache.acc[i].shift-acc[i].shift)); - acc[i].shift = cache.acc[i].shift; - } - } -#endif -} - -void DSPJitRegCache::drop() -{ - merged = true; -} - -void DSPJitRegCache::flushRegs() -{ - //also needs to undo any dynamic changes to static allocated regs - //this should have the same effect as - //merge(DSPJitRegCache(emitter)); -#ifdef _M_X64 -#ifdef ROTATED_REG_ACCS - for(unsigned int i = 0; i < 2; i++) { - if (acc[i].shift > 0) { - emitter.ROL(64, R(acc[i].host_reg), - Imm8(acc[i].shift)); - acc[i].shift = 0; - } - _assert_msg_(DSPLLE, !acc[i].used, - "accumulator still in use"); - if (acc[i].used) - emitter.INT3(); - } -#endif -#endif -} - -static u64 ebp_store; - -void DSPJitRegCache::loadStaticRegs() -{ -#ifdef _M_X64 -#ifdef ROTATED_REG_ACCS - emitter.MOV(64, R(R8), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[0].val))); - emitter.MOV(64, R(R9), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[1].val))); -#endif - emitter.MOV(64, MDisp(R11, PtrOffset(&ebp_store, &g_dsp.r)), R(RBP)); -#else - emitter.MOV(32, M(&ebp_store), R(EBP)); -#endif -} - -void DSPJitRegCache::saveStaticRegs() -{ - flushRegs(); -#ifdef _M_X64 -#ifdef ROTATED_REG_ACCS - emitter.MOV(64, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[0].val)), R(R8)); - emitter.MOV(64, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[1].val)), R(R9)); -#endif - emitter.MOV(64, R(RBP), MDisp(R11, PtrOffset(&ebp_store, &g_dsp.r))); -#else - emitter.MOV(32, R(EBP), M(&ebp_store)); -#endif -} - -void DSPJitRegCache::getReg(int reg, OpArg &oparg, bool load) -{ - switch(reg) { -#ifdef _M_X64 -#ifdef ROTATED_REG_ACCS - case DSP_REG_ACH0: - case DSP_REG_ACH1: - { - _assert_msg_(DSPLLE, !acc[reg-DSP_REG_ACH0].used, - "accumulator already in use"); - if (acc[reg-DSP_REG_ACH0].used) - emitter.INT3(); - oparg = R(acc[reg-DSP_REG_ACH0].host_reg); - if (acc[reg-DSP_REG_ACH0].shift < 32) { - emitter.ROR(64, oparg, Imm8(32-acc[reg-DSP_REG_ACH0].shift)); - acc[reg-DSP_REG_ACH0].shift = 32; - } - - acc[reg-DSP_REG_ACH0].used = true; - } - break; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - { - _assert_msg_(DSPLLE, !acc[reg-DSP_REG_ACM0].used, - "accumulator already in use"); - if (acc[reg-DSP_REG_ACM0].used) - emitter.INT3(); - oparg = R(acc[reg-DSP_REG_ACM0].host_reg); - if (acc[reg-DSP_REG_ACM0].shift < 16) { - emitter.ROR(64, oparg, Imm8(16-acc[reg-DSP_REG_ACM0].shift)); - acc[reg-DSP_REG_ACM0].shift = 16; - } - if (acc[reg-DSP_REG_ACM0].shift > 16) { - emitter.ROL(64, oparg, Imm8(acc[reg-DSP_REG_ACM0].shift-16)); - acc[reg-DSP_REG_ACM0].shift = 16; - } - acc[reg-DSP_REG_ACM0].used = true; - } - break; - case DSP_REG_ACL0: - case DSP_REG_ACL1: - { - _assert_msg_(DSPLLE, !acc[reg-DSP_REG_ACL0].used, - "accumulator already in use"); - if (acc[reg-DSP_REG_ACL0].used) - emitter.INT3(); - oparg = R(acc[reg-DSP_REG_ACL0].host_reg); - if (acc[reg-DSP_REG_ACL0].shift > 0) { - emitter.ROL(64, oparg, Imm8(acc[reg-DSP_REG_ACL0].shift)); - acc[reg-DSP_REG_ACL0].shift = 0; - } - acc[reg-DSP_REG_ACL0].used = true; - } - break; - case DSP_REG_ACC0_64: - case DSP_REG_ACC1_64: - { - if (acc[reg-DSP_REG_ACC0_64].used) - emitter.INT3(); - _assert_msg_(DSPLLE, !acc[reg-DSP_REG_ACC0_64].used, - "accumulator already in use"); - oparg = R(acc[reg-DSP_REG_ACC0_64].host_reg); - if (load) { - if (acc[reg-DSP_REG_ACC0_64].shift > 0) { - emitter.ROL(64, oparg, Imm8(acc[reg-DSP_REG_ACC0_64].shift)); - } - emitter.SHL(64, oparg, Imm8(64-40));//sign extend - emitter.SAR(64, oparg, Imm8(64-40)); - } - //don't bother to rotate if caller replaces all data - acc[reg-DSP_REG_ACC0_64].shift = 0; - acc[reg-DSP_REG_ACC0_64].used = true; - } - break; -#endif -#endif - default: - { -/* - getFreeXReg(reg[reg].host_reg); - X64Reg tmp = reg[reg].host_reg; - oparg = R(tmp); - - if (load) { - u16 *regp = reg_ptr(reg); -#ifdef _M_IX86 // All32 - emitter.MOV(16, oparg, M(regp)); -#else - emitter.MOV(16, oparg, MDisp(R11, PtrOffset(regp, &g_dsp.r))); -#endif - } -*/ - oparg = regs[reg].loc; //when loading/storing from/to mem, need to consider regs[reg].size - } - break; - } -} - -void DSPJitRegCache::putReg(int reg, bool dirty) -{ - switch(reg) { -#ifdef _M_X64 -#ifdef ROTATED_REG_ACCS - case DSP_REG_ACH0: - case DSP_REG_ACH1: - { - - if (dirty) { - if (acc[reg-DSP_REG_ACH0].shift > 0) { - emitter.ROL(64, R(acc[reg-DSP_REG_ACH0].host_reg), - Imm8(acc[reg-DSP_REG_ACH0].shift)); - acc[reg-DSP_REG_ACH0].shift = 0; - } - emitter.SHL(64, R(acc[reg-DSP_REG_ACH0].host_reg), Imm8(64-40));//sign extend - emitter.SAR(64, R(acc[reg-DSP_REG_ACH0].host_reg), Imm8(64-40)); - } - acc[reg-DSP_REG_ACH0].used = false; - } - break; - case DSP_REG_ACM0: - case DSP_REG_ACM1: - { - acc[reg-DSP_REG_ACM0].used = false; - } - break; - case DSP_REG_ACL0: - case DSP_REG_ACL1: - acc[reg-DSP_REG_ACL0].used = false; - break; - case DSP_REG_ACC0_64: - case DSP_REG_ACC1_64: - { - if (dirty) { - OpArg _reg = R(acc[reg-DSP_REG_ACC0_64].host_reg); - - emitter.SHL(64, _reg, Imm8(64-40));//sign extend - emitter.SAR(64, _reg, Imm8(64-40)); - } - acc[reg-DSP_REG_ACC0_64].used = false; - } - break; -#else - case DSP_REG_ACH0: - case DSP_REG_ACH1: - { - //need to fix in memory for now. - u16 *regp = reg_ptr(reg); - OpArg mem; - mem = MDisp(R11,PtrOffset(regp,&g_dsp.r)); - X64Reg tmp; - getFreeXReg(tmp); - // sign extend from the bottom 8 bits. - emitter.MOVSX(16, 8, tmp, mem); - emitter.MOV(16, mem, R(tmp)); - putXReg(tmp); - } - break; -#endif -#else - case DSP_REG_ACH0: - case DSP_REG_ACH1: - { - //need to fix in memory for now. - u16 *regp = reg_ptr(reg); - OpArg mem; - mem = M(regp); - X64Reg tmp; - getFreeXReg(tmp); - // sign extend from the bottom 8 bits. - emitter.MOVSX(16, 8, tmp, mem); - emitter.MOV(16, mem, R(tmp)); - putXReg(tmp); - } - break; -#endif - default: - { -/* - X64Reg tmp = reg[reg].host_reg; - - if(dirty) { - u16 *regp = reg_ptr(reg); -#ifdef _M_IX86 // All32 - emitter.MOV(16, M(dregp), R(tmp)); -#else - emitter.MOV(16, MDisp(R11, PtrOffset(dregp, &g_dsp.r)), R(tmp)); -#endif - } -*/ - } - break; - } -} - -void DSPJitRegCache::readReg(int sreg, X64Reg host_dreg, DSPJitSignExtend extend) -{ - OpArg reg; - getReg(sreg, reg); - switch(regs[sreg].size) { - case 2: - switch(extend) { -#ifdef _M_X64 - case SIGN: emitter.MOVSX(64, 16, host_dreg, reg); break; - case ZERO: emitter.MOVZX(64, 16, host_dreg, reg); break; -#else - case SIGN: emitter.MOVSX(32, 16, host_dreg, reg); break; - case ZERO: emitter.MOVZX(32, 16, host_dreg, reg); break; -#endif - case NONE: emitter.MOV(16, R(host_dreg), reg); break; - } - break; - case 4: -#ifdef _M_X64 - switch(extend) { - case SIGN: emitter.MOVSX(64, 32, host_dreg, reg); break; - case ZERO: emitter.MOVZX(64, 32, host_dreg, reg); break; - case NONE: emitter.MOV(32, R(host_dreg), reg); break; - } -#else - emitter.MOV(32, R(host_dreg), reg); break; -#endif - break; -#ifdef _M_X64 - case 8: - emitter.MOV(64, R(host_dreg), reg); break; - break; -#endif - default: - _assert_msg_(DSPLLE, 0, "unsupported memory size"); - break; - } - putReg(sreg, false); -} - -void DSPJitRegCache::writeReg(int dreg, OpArg arg) -{ - OpArg reg; - getReg(dreg, reg, false); - switch(regs[dreg].size) { - case 2: emitter.MOV(16, reg, arg); break; - case 4: emitter.MOV(32, reg, arg); break; -#ifdef _M_X64 - case 8: emitter.MOV(64, reg, arg); break; -#endif - default: - _assert_msg_(DSPLLE, 0, "unsupported memory size"); - break; - } - putReg(dreg, true); -} - -X64Reg DSPJitRegCache::spillXReg() -{ - //todo: implement - return INVALID_REG; -} - -void DSPJitRegCache::spillXReg(X64Reg reg) -{ - //todo: implement -} - -X64Reg DSPJitRegCache::findFreeXReg() -{ - int i; - for(i = 0; i < NUMXREGS; i++) { - if (xregs[i].guest_reg == DSP_REG_NONE) { - return (X64Reg)i; - } - } - return INVALID_REG; -} - -void DSPJitRegCache::getFreeXReg(X64Reg ®) -{ - reg = findFreeXReg(); - if (reg == INVALID_REG) - reg = spillXReg(); - _assert_msg_(DSPLLE, reg != INVALID_REG, "could not find register"); - xregs[reg].guest_reg = DSP_REG_USED; -} - -void DSPJitRegCache::getXReg(X64Reg reg) -{ - if (xregs[reg].guest_reg != DSP_REG_NONE) - spillXReg(reg); - _assert_msg_(DSPLLE, xregs[reg].guest_reg != DSP_REG_NONE, "register already in use"); - xregs[reg].guest_reg = DSP_REG_USED; -} - -void DSPJitRegCache::putXReg(X64Reg reg) -{ - _assert_msg_(DSPLLE, xregs[reg].guest_reg == DSP_REG_USED, - "putXReg without get(Free)XReg"); - xregs[reg].guest_reg = DSP_REG_NONE; -} diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitRegCache.h b/Source/Core/DSPCore/Src/Jit/DSPJitRegCache.h deleted file mode 100644 index a230947c11..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitRegCache.h +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (C) 2011 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 _DSPJITREGCACHE_H -#define _DSPJITREGCACHE_H - -#include "x64Emitter.h" - -class DSPEmitter; - -enum DSPJitRegSpecial { - DSP_REG_ACC0_64 =32, - DSP_REG_ACC1_64 =33, - DSP_REG_AX0_32 =34, - DSP_REG_AX1_32 =35, - DSP_REG_PROD_64 =36, - DSP_REG_MAX_MEM_BACKED = 36, - - DSP_REG_USED =253, - DSP_REG_STATIC =254, - DSP_REG_NONE =255 -}; - -enum DSPJitSignExtend { - SIGN, ZERO, NONE -}; - -#ifdef _M_X64 -#define NUMXREGS 16 -#elif _M_IX86 -#define NUMXREGS 8 -#endif - -class DSPJitRegCache { -private: - struct X64CachedReg - { - int guest_reg; //including DSPJitRegSpecial - }; - struct DynamicReg { - Gen::OpArg loc; - void *mem; - size_t size; - bool dirty; - }; - -#ifdef _M_X64 - //when there is a way to do this efficiently in x86, uncondition - struct { - Gen::X64Reg host_reg; - int shift; - bool dirty; - bool used; - Gen::X64Reg tmp_reg; - } acc[2]; -#endif - - DynamicReg regs[DSP_REG_MAX_MEM_BACKED+1]; - X64CachedReg xregs[NUMXREGS]; - - DSPEmitter &emitter; - bool temporary; - bool merged; -private: - //find a free host reg - Gen::X64Reg findFreeXReg(); - Gen::X64Reg spillXReg(); - void spillXReg(Gen::X64Reg reg); -public: - DSPJitRegCache(DSPEmitter &_emitter); - - //for branching into multiple control flows - DSPJitRegCache(const DSPJitRegCache &cache); - DSPJitRegCache& operator=(const DSPJitRegCache &cache); - - ~DSPJitRegCache(); - - //merge must be done _before_ leaving the code branch, so we can fix - //up any differences in state - void flushRegs(DSPJitRegCache &cache, bool emit = true); - /* since some use cases are non-trivial, some examples: - - //this does not modify the final state of gpr - <code using gpr> - FixupBranch b = JCC(); - DSPJitRegCache c = gpr; - <code using c> - gpr.flushRegs(c); - SetBranchTarget(b); - <code using gpr> - - //this does not modify the final state of gpr - <code using gpr> - DSPJitRegCache c = gpr; - FixupBranch b1 = JCC(); - <code using gpr> - gpr.flushRegs(c); - FixupBranch b2 = JMP(); - SetBranchTarget(b1); - <code using gpr> - gpr.flushRegs(c); - SetBranchTarget(b2); - <code using gpr> - - //this allows gpr to be modified in the second branch - //and fixes gpr according to the results form in the first branch - <code using gpr> - DSPJitRegCache c = gpr; - FixupBranch b1 = JCC(); - <code using c> - FixupBranch b2 = JMP(); - SetBranchTarget(b1); - <code using gpr> - gpr.flushRegs(c); - SetBranchTarget(b2); - <code using gpr> - - //this does not modify the final state of gpr - <code using gpr> - u8* b = GetCodePtr(); - DSPJitRegCache c = gpr; - <code using gpr> - gpr.flushRegs(c); - JCC(b); - <code using gpr> - - this all is not needed when gpr would not be used at all in the - conditional branch - */ - //drop this copy without warning - void drop(); - - //prepare state so that another flushed DSPJitRegCache can take over - void flushRegs(); - - void loadStaticRegs();//load statically allocated regs from memory - void saveStaticRegs();//save statically allocated regs to memory - - //gives no SCALE_RIP with abs(offset) >= 0x80000000 - void getReg(int reg, Gen::OpArg &oparg, bool load = true); - //done with all usages of OpArg above - void putReg(int reg, bool dirty = true); - - void readReg(int sreg, Gen::X64Reg host_dreg, DSPJitSignExtend extend); - void writeReg(int dreg, Gen::OpArg arg); - - //find a free host reg, spill if used, reserve - void getFreeXReg(Gen::X64Reg ®); - //spill a specific host reg if used, reserve - void getXReg(Gen::X64Reg reg); - //unreserve the given host reg - void putXReg(Gen::X64Reg reg); -}; - -#endif /*_DSPJITREGCACHE_H*/ diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp deleted file mode 100644 index 35e5de9d9a..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp +++ /dev/null @@ -1,596 +0,0 @@ -// Copyright (C) 2010 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 "../DSPMemoryMap.h" -#include "../DSPHWInterface.h" -#include "../DSPEmitter.h" -#include "DSPJitUtil.h" -#include "x64Emitter.h" -#include "ABI.h" - -using namespace Gen; - -// addr math -// -// These functions detect overflow by checking if -// the bit past the top of the mask(WR) has changed in AR. -// They detect values under the minimum for a mask by adding wr + 1 -// and checking if the bit past the top of the mask doesn't change. -// Both are done while ignoring changes due to values/holes in IX -// above the mask. - - -// EAX = g_dsp.r.ar[reg] -// EDX = g_dsp.r.wr[reg] -// EDI = temp -// ECX = temp -void DSPEmitter::increment_addr_reg(int reg) -{ - OpArg ar_reg; - OpArg wr_reg; - gpr.getReg(DSP_REG_WR0+reg,wr_reg); - MOVZX(32, 16, EDX, wr_reg); - gpr.putReg(DSP_REG_WR0+reg); - gpr.getReg(DSP_REG_AR0+reg,ar_reg); - MOVZX(32, 16, EAX, ar_reg); - - //u32 nar = ar + 1; - MOV(32, R(EDI), R(EAX)); - ADD(32, R(EAX), Imm8(1)); - - // if ((nar ^ ar) > ((wr | 1) << 1)) - // nar -= wr + 1; - XOR(32, R(EDI), R(EAX)); - LEA(32, ECX, MComplex(EDX, EDX, 1, 0)); - OR(32, R(ECX), Imm8(2)); - CMP(32, R(EDI), R(ECX)); - FixupBranch nowrap = J_CC(CC_BE); - SUB(16, R(AX), R(DX)); - SUB(16, R(AX), Imm8(1)); - SetJumpTarget(nowrap); - // g_dsp.r.ar[reg] = nar; - - MOV(16, ar_reg, R(AX)); - gpr.putReg(DSP_REG_AR0+reg); -} - -// EAX = g_dsp.r.ar[reg] -// EDX = g_dsp.r.wr[reg] -// EDI = temp -// ECX = temp -void DSPEmitter::decrement_addr_reg(int reg) -{ - OpArg ar_reg; - OpArg wr_reg; - gpr.getReg(DSP_REG_WR0+reg,wr_reg); - MOVZX(32, 16, EDX, wr_reg); - gpr.putReg(DSP_REG_WR0+reg); - gpr.getReg(DSP_REG_AR0+reg,ar_reg); - MOVZX(32, 16, EAX, ar_reg); - - // u32 nar = ar + wr; - // edi = nar - LEA(32, EDI, MComplex(EAX, EDX, 1, 0)); - - // if (((nar ^ ar) & ((wr | 1) << 1)) > wr) - // nar -= wr + 1; - XOR(32, R(EAX), R(EDI)); - LEA(32, ECX, MComplex(EDX, EDX, 1, 0)); - OR(32, R(ECX), Imm8(2)); - AND(32, R(EAX), R(ECX)); - CMP(32, R(EAX), R(EDX)); - FixupBranch nowrap = J_CC(CC_BE); - SUB(16, R(DI), R(DX)); - SUB(16, R(DI), Imm8(1)); - SetJumpTarget(nowrap); - // g_dsp.r.ar[reg] = nar; - - MOV(16, ar_reg, R(DI)); - gpr.putReg(DSP_REG_AR0+reg); -} - -// Increase addr register according to the correspond ix register -// EAX = g_dsp.r.ar[reg] -// EDX = g_dsp.r.wr[reg] -// ESI = g_dsp.r.ix[reg] -// ECX = temp -// EDI = temp -void DSPEmitter::increase_addr_reg(int reg) -{ - OpArg ar_reg; - OpArg wr_reg; - OpArg ix_reg; - gpr.getReg(DSP_REG_WR0+reg,wr_reg); - gpr.getReg(DSP_REG_IX0+reg,ix_reg); - MOVZX(32, 16, EDX, wr_reg); - MOVSX(32, 16, ESI, ix_reg); - gpr.putReg(DSP_REG_WR0+reg); - gpr.putReg(DSP_REG_IX0+reg); - gpr.getReg(DSP_REG_AR0+reg,ar_reg); - MOVZX(32, 16, EAX, ar_reg); - - //u32 nar = ar + ix; - //edi = nar - LEA(32, EDI, MComplex(EAX, ESI, 1, 0)); - - //u32 dar = (nar ^ ar ^ ix) & ((wr | 1) << 1); - //eax = dar - XOR(32, R(EAX), R(ESI)); - XOR(32, R(EAX), R(EDI)); - LEA(32, ECX, MComplex(EDX, EDX, 1, 0)); - OR(32, R(ECX), Imm8(2)); - AND(32, R(EAX), R(ECX)); - - //if (ix >= 0) - TEST(32, R(ESI), R(ESI)); - FixupBranch negative = J_CC(CC_S); - //if (dar > wr) - CMP(32, R(EAX), R(EDX)); - FixupBranch done = J_CC(CC_BE); - //nar -= wr + 1; - SUB(16, R(DI), R(DX)); - SUB(16, R(DI), Imm8(1)); - FixupBranch done2 = J(); - - //else - SetJumpTarget(negative); - //if ((((nar + wr + 1) ^ nar) & dar) <= wr) - LEA(32, ECX, MComplex(EDI, EDX, 1, 1)); - XOR(32, R(ECX), R(EDI)); - AND(32, R(ECX), R(EAX)); - CMP(32, R(ECX), R(EDX)); - FixupBranch done3 = J_CC(CC_A); - //nar += wr + 1; - LEA(32, EDI, MComplex(EDI, EDX, 1, 1)); - - SetJumpTarget(done); - SetJumpTarget(done2); - SetJumpTarget(done3); - // g_dsp.r.ar[reg] = nar; - - MOV(16, ar_reg, R(DI)); - gpr.putReg(DSP_REG_AR0+reg); -} - -// Decrease addr register according to the correspond ix register -// EAX = g_dsp.r.ar[reg] -// EDX = g_dsp.r.wr[reg] -// ESI = g_dsp.r.ix[reg] -// ECX = temp -// EDI = temp -void DSPEmitter::decrease_addr_reg(int reg) -{ - OpArg ar_reg; - OpArg wr_reg; - OpArg ix_reg; - gpr.getReg(DSP_REG_WR0+reg,wr_reg); - gpr.getReg(DSP_REG_IX0+reg,ix_reg); - MOVZX(32, 16, EDX, wr_reg); - MOVSX(32, 16, ESI, ix_reg); - gpr.putReg(DSP_REG_WR0+reg); - gpr.putReg(DSP_REG_IX0+reg); - gpr.getReg(DSP_REG_AR0+reg,ar_reg); - MOVZX(32, 16, EAX, ar_reg); - - NOT(32, R(ESI)); //esi = ~ix - - //u32 nar = ar - ix; (ar + ~ix + 1) - LEA(32, EDI, MComplex(EAX, ESI, 1, 1)); - - //u32 dar = (nar ^ ar ^ ~ix) & ((wr | 1) << 1); - //eax = dar - XOR(32, R(EAX), R(ESI)); - XOR(32, R(EAX), R(EDI)); - LEA(32, ECX, MComplex(EDX, EDX, 1, 0)); - OR(32, R(ECX), Imm8(2)); - AND(32, R(EAX), R(ECX)); - - //if ((u32)ix > 0xFFFF8000) ==> (~ix < 0x00007FFF) - CMP(32, R(ESI), Imm32(0x00007FFF)); - FixupBranch positive = J_CC(CC_AE); - //if (dar > wr) - CMP(32, R(EAX), R(EDX)); - FixupBranch done = J_CC(CC_BE); - //nar -= wr + 1; - SUB(16, R(DI), R(DX)); - SUB(16, R(DI), Imm8(1)); - FixupBranch done2 = J(); - - //else - SetJumpTarget(positive); - //if ((((nar + wr + 1) ^ nar) & dar) <= wr) - LEA(32, ECX, MComplex(EDI, EDX, 1, 1)); - XOR(32, R(ECX), R(EDI)); - AND(32, R(ECX), R(EAX)); - CMP(32, R(ECX), R(EDX)); - FixupBranch done3 = J_CC(CC_A); - //nar += wr + 1; - LEA(32, EDI, MComplex(EDI, EDX, 1, 1)); - - SetJumpTarget(done); - SetJumpTarget(done2); - SetJumpTarget(done3); - //return nar - - MOV(16, ar_reg, R(DI)); - gpr.putReg(DSP_REG_AR0+reg); -} - - -// EAX - destination address -// ECX - value -// ESI - Base of dram -void DSPEmitter::dmem_write() -{ - // if (saddr == 0) - CMP(16, R(EAX), Imm16(0x0fff)); - FixupBranch ifx = J_CC(CC_A); - - // g_dsp.dram[addr & DSP_DRAM_MASK] = val; - AND(16, R(EAX), Imm16(DSP_DRAM_MASK)); -#ifdef _M_X64 - MOV(64, R(ESI), ImmPtr(g_dsp.dram)); -#else - MOV(32, R(ESI), ImmPtr(g_dsp.dram)); -#endif - MOV(16, MComplex(ESI, EAX, 2, 0), R(ECX)); - - FixupBranch end = J(); - // else if (saddr == 0xf) - SetJumpTarget(ifx); - // Does it mean gdsp_ifx_write needs u32 rather than u16? - DSPJitRegCache c(gpr); - SaveDSPRegs(); - ABI_CallFunctionRR((void *)gdsp_ifx_write, EAX, ECX); - LoadDSPRegs(); - gpr.flushRegs(c); - SetJumpTarget(end); -} - -// ECX - value -void DSPEmitter::dmem_write_imm(u16 address) -{ - switch (address >> 12) - { - case 0x0: // 0xxx DRAM -#ifdef _M_IX86 // All32 - MOV(16, M(&g_dsp.dram[address & DSP_DRAM_MASK]), R(ECX)); -#else - MOV(64, R(RDX), ImmPtr(g_dsp.dram)); - MOV(16, MDisp(RDX, (address & DSP_DRAM_MASK)*2), R(ECX)); -#endif - break; - - case 0xf: // Fxxx HW regs - MOV(16, R(EAX), Imm16(address)); - SaveDSPRegs(); - ABI_CallFunctionRR((void *)gdsp_ifx_write, EAX, ECX); - LoadDSPRegs(); - break; - - default: // Unmapped/non-existing memory - ERROR_LOG(DSPLLE, "%04x DSP ERROR: Write to UNKNOWN (%04x) memory", - g_dsp.pc, address); - break; - } -} - -// In: ECX - the address to read -// Out: EAX - the result of the read (used by caller) -// ESI - Base -void DSPEmitter::imem_read() -{ - // if (addr == 0) - CMP(16, R(ECX), Imm16(0x0fff)); - FixupBranch irom = J_CC(CC_A); - // return g_dsp.iram[addr & DSP_IRAM_MASK]; - AND(16, R(ECX), Imm16(DSP_IRAM_MASK)); -#ifdef _M_X64 - MOV(64, R(ESI), ImmPtr(g_dsp.iram)); -#else - MOV(32, R(ESI), ImmPtr(g_dsp.iram)); -#endif - MOV(16, R(EAX), MComplex(ESI, ECX, 2, 0)); - - FixupBranch end = J(); - SetJumpTarget(irom); - // else if (addr == 0x8) - // return g_dsp.irom[addr & DSP_IROM_MASK]; - AND(16, R(ECX), Imm16(DSP_IROM_MASK)); -#ifdef _M_X64 - MOV(64, R(ESI), ImmPtr(g_dsp.irom)); -#else - MOV(32, R(ESI), ImmPtr(g_dsp.irom)); -#endif - MOV(16, R(EAX), MComplex(ESI, ECX, 2, 0)); - - SetJumpTarget(end); -} - -// In: ECX - the address to read -// Out: EAX - the result of the read (used by caller) -// ESI - Base -// Trashes R11 on gdsp_ifx_read -void DSPEmitter::dmem_read() -{ - // if (saddr == 0) - CMP(16, R(ECX), Imm16(0x0fff)); - FixupBranch dram = J_CC(CC_A); - // return g_dsp.dram[addr & DSP_DRAM_MASK]; -#ifdef _M_X64 - AND(16, R(ECX), Imm16(DSP_DRAM_MASK)); - MOVZX(64, 16, RCX, R(RCX)); - MOV(64, R(ESI), ImmPtr(g_dsp.dram)); -#else - AND(32, R(ECX), Imm32(DSP_DRAM_MASK)); - MOV(32, R(ESI), ImmPtr(g_dsp.dram)); -#endif - MOV(16, R(EAX), MComplex(ESI, ECX, 2, 0)); - - FixupBranch end = J(); - SetJumpTarget(dram); - // else if (saddr == 0x1) - CMP(16, R(ECX), Imm16(0x1fff)); - FixupBranch ifx = J_CC(CC_A); - // return g_dsp.coef[addr & DSP_COEF_MASK]; -#ifdef _M_X64 - AND(16, R(ECX), Imm16(DSP_COEF_MASK)); - MOVZX(64, 16, RCX, R(RCX)); - MOV(64, R(ESI), ImmPtr(g_dsp.coef)); -#else - AND(32, R(ECX), Imm32(DSP_COEF_MASK)); - MOV(32, R(ESI), ImmPtr(g_dsp.coef)); -#endif - MOV(16, R(EAX), MComplex(ESI, ECX, 2, 0)); - - FixupBranch end2 = J(); - SetJumpTarget(ifx); - // else if (saddr == 0xf) - // return gdsp_ifx_read(addr); - DSPJitRegCache c(gpr); - SaveDSPRegs(); - ABI_CallFunctionR((void *)gdsp_ifx_read, ECX); - LoadDSPRegs(); - gpr.flushRegs(c); - SetJumpTarget(end); - SetJumpTarget(end2); -} - -void DSPEmitter::dmem_read_imm(u16 address) -{ - switch (address >> 12) - { - case 0x0: // 0xxx DRAM -#ifdef _M_IX86 // All32 - MOV(16, R(EAX), M(&g_dsp.dram[address & DSP_DRAM_MASK])); -#else - MOV(64, R(RDX), ImmPtr(g_dsp.dram)); - MOV(16, R(EAX), MDisp(RDX, (address & DSP_DRAM_MASK)*2)); -#endif - break; - - case 0x1: // 1xxx COEF -#ifdef _M_IX86 // All32 - MOV(16, R(EAX), Imm16(g_dsp.coef[address & DSP_COEF_MASK])); -#else - MOV(64, R(RDX), ImmPtr(g_dsp.coef)); - MOV(16, R(EAX), MDisp(RDX, (address & DSP_COEF_MASK)*2)); -#endif - break; - - case 0xf: // Fxxx HW regs - SaveDSPRegs(); - ABI_CallFunctionC16((void *)gdsp_ifx_read, address); - LoadDSPRegs(); - break; - - default: // Unmapped/non-existing memory - ERROR_LOG(DSPLLE, "%04x DSP ERROR: Read from UNKNOWN (%04x) memory", - g_dsp.pc, address); - } -} - -// Returns s64 in RAX -void DSPEmitter::get_long_prod(X64Reg long_prod) -{ -#ifdef _M_X64 - // MOV(64, R(R11), ImmPtr(&g_dsp.r)); - //s64 val = (s8)(u8)g_dsp.r[DSP_REG_PRODH]; - OpArg reg; - gpr.getReg(DSP_REG_PROD_64, reg); - X64Reg tmp; - gpr.getFreeXReg(tmp); - MOV(64, R(long_prod), reg); - MOV(64, R(tmp), R(long_prod)); - SHL(64, R(long_prod), Imm8(64-40));//sign extend - SAR(64, R(long_prod), Imm8(64-40)); - SHR(64, R(tmp), Imm8(48)); - SHL(64, R(tmp), Imm8(16)); - ADD(64, R(long_prod), R(tmp)); - gpr.putXReg(tmp); - gpr.putReg(DSP_REG_PROD_64, false); - -#endif -} - -// Returns s64 in RAX -// Clobbers RSI -void DSPEmitter::get_long_prod_round_prodl(X64Reg long_prod) -{ -#ifdef _M_X64 - //s64 prod = dsp_get_long_prod(); - get_long_prod(long_prod); - - //if (prod & 0x10000) prod = (prod + 0x8000) & ~0xffff; - TEST(32, R(long_prod), Imm32(0x10000)); - FixupBranch jump = J_CC(CC_Z); - ADD(64, R(long_prod), Imm32(0x8000)); - MOV(64, R(ESI), Imm64(~0xffff)); - AND(64, R(long_prod), R(RSI)); - FixupBranch _ret = J(); - //else prod = (prod + 0x7fff) & ~0xffff; - SetJumpTarget(jump); - ADD(64, R(long_prod), Imm32(0x7fff)); - MOV(64, R(RSI), Imm64(~0xffff)); - AND(64, R(long_prod), R(RSI)); - SetJumpTarget(_ret); - //return prod; -#endif -} - -// For accurate emulation, this is wrong - but the real prod registers behave -// in completely bizarre ways. Probably not meaningful to emulate them accurately. -// In: RAX = s64 val -void DSPEmitter::set_long_prod() -{ -#ifdef _M_X64 - OpArg reg; - gpr.getReg(DSP_REG_PROD_64, reg, false); - X64Reg tmp; - gpr.getFreeXReg(tmp); - - MOV(64, R(tmp), Imm64(0x000000ffffffffffULL)); - AND(64, R(RAX), R(tmp)); - // g_dsp.r[DSP_REG_PRODL] = (u16)val; - MOV(64, reg, R(RAX)); - - gpr.putXReg(tmp); - gpr.putReg(DSP_REG_PROD_64, true); -#endif -} - -// Returns s64 in RAX -// Clobbers RSI -void DSPEmitter::round_long_acc(X64Reg long_acc) -{ -#ifdef _M_X64 - //if (prod & 0x10000) prod = (prod + 0x8000) & ~0xffff; - TEST(32, R(long_acc), Imm32(0x10000)); - FixupBranch jump = J_CC(CC_Z); - ADD(64, R(long_acc), Imm32(0x8000)); - MOV(64, R(ESI), Imm64(~0xffff)); - AND(64, R(long_acc), R(RSI)); - FixupBranch _ret = J(); - //else prod = (prod + 0x7fff) & ~0xffff; - SetJumpTarget(jump); - ADD(64, R(long_acc), Imm32(0x7fff)); - MOV(64, R(RSI), Imm64(~0xffff)); - AND(64, R(long_acc), R(RSI)); - SetJumpTarget(_ret); - //return prod; -#endif -} - -// Returns s64 in acc -void DSPEmitter::get_long_acc(int _reg, X64Reg acc) -{ -#ifdef _M_X64 - OpArg reg; - gpr.getReg(DSP_REG_ACC0_64+_reg, reg); - MOV(64, R(acc), reg); - gpr.putReg(DSP_REG_ACC0_64+_reg, false); -#endif -} - -// In: acc = s64 val -void DSPEmitter::set_long_acc(int _reg, X64Reg acc) -{ -#ifdef _M_X64 - OpArg reg; - gpr.getReg(DSP_REG_ACC0_64+_reg, reg, false); - MOV(64, reg, R(acc)); - gpr.putReg(DSP_REG_ACC0_64+_reg); -#endif -} - -// Returns s16 in AX -void DSPEmitter::get_acc_l(int _reg, X64Reg acl, bool sign) -{ - // return g_dsp.r[DSP_REG_ACM0 + _reg]; - gpr.readReg(_reg+DSP_REG_ACL0, acl, sign?SIGN:ZERO); -} - -void DSPEmitter::set_acc_l(int _reg, OpArg arg) -{ - // return g_dsp.r[DSP_REG_ACM0 + _reg]; - gpr.writeReg(_reg+DSP_REG_ACL0,arg); -} - -// Returns s16 in AX -void DSPEmitter::get_acc_m(int _reg, X64Reg acm, bool sign) -{ -// return g_dsp.r[DSP_REG_ACM0 + _reg]; - gpr.readReg(_reg+DSP_REG_ACM0, acm, sign?SIGN:ZERO); -} - -// In: s16 in AX -void DSPEmitter::set_acc_m(int _reg, OpArg arg) -{ - // return g_dsp.r.ac[_reg].m; - gpr.writeReg(_reg+DSP_REG_ACM0,arg); -} - -// Returns s16 in AX -void DSPEmitter::get_acc_h(int _reg, X64Reg ach, bool sign) -{ -// return g_dsp.r.ac[_reg].h; - gpr.readReg(_reg+DSP_REG_ACH0, ach, sign?SIGN:ZERO); -} - -// In: s16 in AX -void DSPEmitter::set_acc_h(int _reg, OpArg arg) -{ - // return g_dsp.r[DSP_REG_ACM0 + _reg]; - gpr.writeReg(_reg+DSP_REG_ACH0,arg); -} - -// Returns u32 in EAX -void DSPEmitter::get_long_acx(int _reg, X64Reg acx) -{ -// return ((u32)g_dsp.r[DSP_REG_AXH0 + _reg] << 16) | g_dsp.r[DSP_REG_AXL0 + _reg]; - gpr.readReg(_reg+DSP_REG_AX0_32, acx, SIGN); -} - -// Returns s16 in EAX -void DSPEmitter::get_ax_l(int _reg, X64Reg axl) -{ -// return (s16)g_dsp.r[DSP_REG_AXL0 + _reg]; - gpr.readReg(_reg+DSP_REG_AXL0, axl, SIGN); -} - -// Returns s16 in EAX -void DSPEmitter::get_ax_h(int _reg, X64Reg axh) -{ -// return (s16)g_dsp.r[DSP_REG_AXH0 + _reg]; - gpr.readReg(_reg+DSP_REG_AXH0, axh, SIGN); -} - -void DSPEmitter::LoadDSPRegs() -{ -#ifdef _M_X64 - MOV(64, R(R11), ImmPtr(&g_dsp.r)); -#endif - - // Load DSP register state here... - gpr.loadStaticRegs(); -} - -void DSPEmitter::SaveDSPRegs() -{ - // Save DSP register state here... - gpr.saveStaticRegs(); -} diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.h b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.h deleted file mode 100644 index 2d28b6d520..0000000000 --- a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (C) 2010 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 __DSPJITUTIL_H__ -#define __DSPJITUTIL_H__ - -#endif /*__DSPJITUTIL_H__*/ diff --git a/Source/Core/DSPCore/Src/LabelMap.cpp b/Source/Core/DSPCore/Src/LabelMap.cpp deleted file mode 100644 index bc6b8d7ba2..0000000000 --- a/Source/Core/DSPCore/Src/LabelMap.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2003 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(); -} diff --git a/Source/Core/DSPCore/Src/LabelMap.h b/Source/Core/DSPCore/Src/LabelMap.h deleted file mode 100644 index 2bdaee9049..0000000000 --- a/Source/Core/DSPCore/Src/LabelMap.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2003 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 diff --git a/Source/Core/DSPCore/Src/SConscript b/Source/Core/DSPCore/Src/SConscript deleted file mode 100644 index f97a15753c..0000000000 --- a/Source/Core/DSPCore/Src/SConscript +++ /dev/null @@ -1,37 +0,0 @@ -# -*- python -*- - -Import('env') - -files = [ - "assemble.cpp", - "disassemble.cpp", - "DSPAccelerator.cpp", - "DSPIntCCUtil.cpp", - "DSPIntExtOps.cpp", - "DSPHWInterface.cpp", - "DSPMemoryMap.cpp", - "DSPStacks.cpp", - "DSPAnalyzer.cpp", - "DspIntArithmetic.cpp", - "DspIntBranch.cpp", - "DspIntLoadStore.cpp", - "DspIntMisc.cpp", - "DspIntMultiplier.cpp", - "DSPEmitter.cpp", - "DSPCodeUtil.cpp", - "LabelMap.cpp", - "DSPInterpreter.cpp", - "DSPCore.cpp", - "DSPTables.cpp", - "Jit/DSPJitExtOps.cpp", - "Jit/DSPJitBranch.cpp", - "Jit/DSPJitUtil.cpp", - "Jit/DSPJitCCUtil.cpp", - "Jit/DSPJitArithmetic.cpp", - "Jit/DSPJitLoadStore.cpp", - "Jit/DSPJitMultiplier.cpp", - "Jit/DSPJitMisc.cpp", - "Jit/DSPJitRegCache.cpp", - ] - -env.StaticLibrary(env['local_libs'] + 'dspcore', files) diff --git a/Source/Core/DSPCore/Src/assemble.cpp b/Source/Core/DSPCore/Src/assemble.cpp deleted file mode 100644 index a8a24e45c2..0000000000 --- a/Source/Core/DSPCore/Src/assemble.cpp +++ /dev/null @@ -1,1020 +0,0 @@ -/*==================================================================== - -$Id: assemble.cpp,v 1.3 2008-11-11 01:04:26 wntrmute Exp $ - -project: GameCube DSP Tool (gcdsp) -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. - -Revision 1.4 2008/10/04 10:30:00 Hermes -added function to export the code to .h file -added support for '/ *' '* /' and '//' for comentaries -added some sintax detection when use registers - -$Log: not supported by cvs2svn $ -Revision 1.2 2005/09/14 02:19:29 wntrmute -added header guards -use standard main function - -Revision 1.1 2005/08/24 22:13:34 wntrmute -Initial import - - -====================================================================*/ - -#include <cstdio> -#include <cstdlib> - -#include <map> -#include <iostream> -#include <fstream> - -#include "Common.h" -#include "FileUtil.h" -#include "DSPInterpreter.h" -#include "DSPTables.h" -#include "disassemble.h" -#include "assemble.h" - -static const char *err_string[] = -{ - "", - "Unknown Error", - "Unknown opcode", - "Not enough parameters", - "Too many parameters", - "Wrong parameter", - "Expected parameter of type 'string'", - "Expected parameter of type 'value'", - "Expected parameter of type 'register'", - "Expected parameter of type 'memory pointer'", - "Expected parameter of type 'immediate'", - "Incorrect binary value", - "Incorrect hexadecimal value", - "Incorrect decimal value", - "Label already exists", - "Label not defined", - "No matching brackets", - "This opcode cannot be extended", - "Given extending params for non extensible opcode", - "Wrong parameter: must be accumulator register", - "Wrong parameter: must be mid accumulator register", - "Invalid register", - "Number out of range" -}; - -DSPAssembler::DSPAssembler(const AssemblerSettings &settings) : - gdg_buffer(NULL), - m_cur_addr(0), - m_cur_pass(0), - m_current_param(0), - settings_(settings) - -{ -} - -DSPAssembler::~DSPAssembler() -{ - if(gdg_buffer) - free(gdg_buffer); -} - -bool DSPAssembler::Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers) -{ - if (line_numbers) - line_numbers->clear(); - const char *fname = "tmp.asm"; - if (!File::WriteStringToFile(true, text, fname)) - return false; - InitPass(1); - if (!AssembleFile(fname, 1)) - return false; - - // We now have the size of the output buffer - if (m_totalSize > 0) - { - gdg_buffer = (char *)malloc(m_totalSize * sizeof(u16) + 4); - if(!gdg_buffer) - return false; - - memset(gdg_buffer, 0, m_totalSize * sizeof(u16)); - } else - return false; - - InitPass(2); - if (!AssembleFile(fname, 2)) - return false; - - code.resize(m_totalSize); - for (int i = 0; i < m_totalSize; i++) { - code[i] = *(u16 *)(gdg_buffer + i * 2); - } - - if(gdg_buffer) { - free(gdg_buffer); - gdg_buffer = NULL; - } - - last_error_str = "(no errors)"; - last_error = ERR_OK; - - return true; -} - -void DSPAssembler::ShowError(err_t err_code, const char *extra_info) -{ - - if (!settings_.force) - failed = true; - - char error_buffer[1024]; - char *buf_ptr = error_buffer; - buf_ptr += sprintf(buf_ptr, "%i : %s ", code_line, cur_line.c_str()); - if (!extra_info) - extra_info = "-"; - - if (m_current_param == 0) - buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d : %s\n", err_string[err_code], code_line, extra_info); - else - buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d Param: %d : %s\n", - err_string[err_code], code_line, m_current_param, extra_info); - last_error_str = error_buffer; - last_error = err_code; -} - -char *skip_spaces(char *ptr) -{ - while (*ptr == ' ') - ptr++; - return ptr; -} - -const char *skip_spaces(const char *ptr) -{ - while (*ptr == ' ') - ptr++; - return ptr; -} - -// Parse a standalone value - it can be a number in one of several formats or a label. -s32 DSPAssembler::ParseValue(const char *str) -{ - bool negative = false; - s32 val = 0; - const char *ptr = str; - - if (ptr[0] == '#') - { - ptr++; - negative = true; // Wow! Double # (needed one to get in here) negates??? - } - if (ptr[0] == '-') - { - ptr++; - negative = true; - } - if (ptr[0] == '0') - { - if (ptr[1] >= '0' && ptr[1] <= '9') - { - for (int i = 0; ptr[i] != 0; i++) - { - val *= 10; - if (ptr[i] >= '0' && ptr[i] <= '9') - val += ptr[i] - '0'; - else - ShowError(ERR_INCORRECT_DEC, str); - } - } - else - { - switch (ptr[1]) - { - case 'X': // hex - for (int i = 2 ; ptr[i] != 0 ; i++) - { - val <<= 4; - if (ptr[i] >= 'a' && ptr[i] <= 'f') - val += (ptr[i]-'a'+10); - else if (ptr[i] >= 'A' && ptr[i] <= 'F') - val += (ptr[i]-'A'+10); - else if (ptr[i] >= '0' && ptr[i] <= '9') - val += (ptr[i] - '0'); - else - ShowError(ERR_INCORRECT_HEX, str); - } - break; - case '\'': // binary - for (int i = 2; ptr[i] != 0; i++) - { - val *=2; - if(ptr[i] >= '0' && ptr[i] <= '1') - val += ptr[i] - '0'; - else - ShowError(ERR_INCORRECT_BIN, str); - } - break; - default: - // value is 0 or error - val = 0; - break; - } - } - } - else - { - // Symbol starts with a digit - it's a dec number. - if (ptr[0] >= '0' && ptr[0] <= '9') - { - for (int i = 0; ptr[i] != 0; i++) - { - val *= 10; - if (ptr[i] >= '0' && ptr[i] <= '9') - val += ptr[i] - '0'; - else - ShowError(ERR_INCORRECT_DEC, str); - } - } - else // Everything else is a label. - { - // Lookup label - u16 value; - if (labels.GetLabelValue(ptr, &value)) - return value; - if (m_cur_pass == 2) - ShowError(ERR_UNKNOWN_LABEL, str); - } - } - if (negative) - return -val; - return val; -} - -// Modifies both src and dst! -// What does it do, really?? -char *DSPAssembler::FindBrackets(char *src, char *dst) -{ - s32 len = (s32) strlen(src); - s32 first = -1; - s32 count = 0; - s32 i, j; - j = 0; - for (i = 0 ; i < len ; i++) - { - if (src[i] == '(') - { - if (first < 0) - { - count = 1; - src[i] = 0x0; - first = i; - } - else - { - count++; - dst[j++] = src[i]; - } - } - else if (src[i] == ')') - { - if (--count == 0) - { - dst[j] = 0; - return &src[i+1]; - } - else - { - dst[j++] = src[i]; - } - } - else - { - if (first >= 0) - dst[j++] = src[i]; - } - } - if (count) - ShowError(ERR_NO_MATCHING_BRACKETS); - return NULL; -} - -// Bizarre in-place expression evaluator. -u32 DSPAssembler::ParseExpression(const char *ptr) -{ - char *pbuf; - s32 val = 0; - - char *d_buffer = (char *)malloc(1024); - char *s_buffer = (char *)malloc(1024); - strcpy(s_buffer, ptr); - - while ((pbuf = FindBrackets(s_buffer, d_buffer)) != NULL) - { - val = ParseExpression(d_buffer); - sprintf(d_buffer, "%s%d%s", s_buffer, val, pbuf); - strcpy(s_buffer, d_buffer); - } - - int j = 0; - for (int i = 0; i < ((s32)strlen(s_buffer) + 1) ; i++) - { - char c = s_buffer[i]; - if (c != ' ') - d_buffer[j++] = c; - } - - for (int i = 0; i < ((s32)strlen(d_buffer) + 1) ; i++) - { - char c = d_buffer[i]; - if (c == '-') - { - if (i == 0) - c = '#'; - else - { - switch (d_buffer[i - 1]) - { - case '/': - case '%': - case '*': - c = '#'; - } - } - } - d_buffer[i] = c; - } - - while ((pbuf = strstr(d_buffer, "+")) != NULL) - { - *pbuf = 0x0; - val = ParseExpression(d_buffer) + ParseExpression(pbuf+1); - sprintf(d_buffer, "%d", val); - } - - while ((pbuf = strstr(d_buffer, "-")) != NULL) - { - *pbuf = 0x0; - val = ParseExpression(d_buffer) - ParseExpression(pbuf+1); - if (val < 0) - { - val = 0x10000 + (val & 0xffff); // ATTENTION: avoid a terrible bug!!! number cannot write with '-' in sprintf - fprintf(stderr, "WARNING: Number Underflow at Line: %d \n", code_line); - } - sprintf(d_buffer, "%d", val); - } - - while ((pbuf = strstr(d_buffer, "*")) != NULL) - { - *pbuf = 0x0; - val = ParseExpression(d_buffer) * ParseExpression(pbuf+1); - sprintf(d_buffer, "%d", val); - } - - while ((pbuf = strstr(d_buffer, "/")) != NULL) - { - *pbuf = 0x0; - val = ParseExpression(d_buffer) / ParseExpression(pbuf+1); - sprintf(d_buffer, "%d", val); - } - - while ((pbuf = strstr(d_buffer, "|")) != NULL) - { - *pbuf = 0x0; - val = ParseExpression(d_buffer) | ParseExpression(pbuf+1); - sprintf(d_buffer, "%d", val); - } - - while ((pbuf = strstr(d_buffer, "&")) != NULL) - { - *pbuf = 0x0; - val = ParseExpression(d_buffer) & ParseExpression(pbuf+1); - sprintf(d_buffer, "%d", val); - } - - val = ParseValue(d_buffer); - free(d_buffer); - free(s_buffer); - return val; -} - -// Destroys parstr -u32 DSPAssembler::GetParams(char *parstr, param_t *par) -{ - u32 count = 0; - char *tmpstr = skip_spaces(parstr); - tmpstr = strtok(tmpstr, ",\x00"); - for (int i = 0; i < 10; i++) - { - if (tmpstr == NULL) - break; - tmpstr = skip_spaces(tmpstr); - if (strlen(tmpstr) == 0) - break; - if (tmpstr) - count++; - else - break; - - par[i].type = P_NONE; - switch (tmpstr[0]) - { - case '"': - par[i].str = strtok(tmpstr, "\""); - par[i].type = P_STR; - break; - case '#': - par[i].val = ParseExpression(tmpstr + 1); - par[i].type = P_IMM; - break; - case '@': - if (tmpstr[1] == '$') - { - par[i].val = ParseExpression(tmpstr + 2); - par[i].type = P_PRG; - } - else - { - par[i].val = ParseExpression(tmpstr + 1); - par[i].type = P_MEM; - } - break; - case '$': - par[i].val = ParseExpression(tmpstr + 1); - par[i].type = P_REG; - break; - - default: - par[i].val = ParseExpression(tmpstr); - par[i].type = P_VAL; - break; - } - tmpstr = strtok(NULL, ",\x00"); - } - return count; -} - -const opc_t *DSPAssembler::FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size) -{ - if (opcode[0] == 'C' && opcode[1] == 'W') - return &cw; - - AliasMap::const_iterator alias_iter = aliases.find(opcode); - if (alias_iter != aliases.end()) - opcode = alias_iter->second.c_str(); - for (int i = 0; i < opcod_size; i++) - { - const opc_t *opc = &opcod[i]; - if (strcmp(opc->name, opcode) == 0) - { - if (par_count < opc->param_count) - { - ShowError(ERR_NOT_ENOUGH_PARAMETERS); - } - if (par_count > opc->param_count) - { - ShowError(ERR_TOO_MANY_PARAMETERS); - } - return opc; - } - } - ShowError(ERR_UNKNOWN_OPCODE); - return NULL; -} - -// weird... -u16 get_mask_shifted_down(u16 mask) -{ - while (!(mask & 1)) - mask >>= 1; - return mask; -} - -bool DSPAssembler::VerifyParams(const opc_t *opc, param_t *par, int count, bool ext) -{ - for (int i = 0; i < count; i++) - { - const int current_param = i + 1; // just for display. - if (opc->params[i].type != par[i].type || (par[i].type & P_REG)) - { - if (par[i].type == P_VAL && - (opc->params[i].type == P_ADDR_I || opc->params[i].type == P_ADDR_D)) - { - // Data and instruction addresses are valid as VAL values. - continue; - } - - if ((opc->params[i].type & P_REG) && (par[i].type & P_REG)) - { - // Just a temp. Should be replaced with more purposeful vars. - int value; - - // modified by Hermes: test the register range - switch ((unsigned)opc->params[i].type) - { - case P_REG18: - case P_REG19: - case P_REG1A: - value = (opc->params[i].type >> 8) & 31; - if ((int)par[i].val < value || - (int)par[i].val > value + get_mask_shifted_down(opc->params[i].mask)) - { - if (ext) fprintf(stderr, "(ext) "); - fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param); - ShowError(ERR_INVALID_REGISTER); - } - break; - case P_PRG: - if ((int)par[i].val < 0 || (int)par[i].val > 0x3) - { - if (ext) fprintf(stderr, "(ext) "); - fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param); - ShowError(ERR_INVALID_REGISTER); - } - break; - case P_ACC: - if ((int)par[i].val < 0x20 || (int)par[i].val > 0x21) - { - if (ext) fprintf(stderr, "(ext) "); - if (par[i].val >= 0x1e && par[i].val <= 0x1f) { - fprintf(stderr, "%i : %s ", code_line, cur_line.c_str()); - fprintf(stderr, "WARNING: $ACM%d register used instead of $ACC%d register Line: %d Param: %d Ext: %d\n", - (par[i].val & 1), (par[i].val & 1), code_line, current_param, ext); - } - else if (par[i].val >= 0x1c && par[i].val <= 0x1d) { - fprintf(stderr, "WARNING: $ACL%d register used instead of $ACC%d register Line: %d Param: %d\n", - (par[i].val & 1), (par[i].val & 1), code_line, current_param); - } - else - ShowError(ERR_WRONG_PARAMETER_ACC); - } - break; - case P_ACCM: - if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f) - { - if (ext) fprintf(stderr, "(ext) "); - if (par[i].val >= 0x1c && par[i].val <= 0x1d) - fprintf(stderr, "WARNING: $ACL%d register used instead of $ACM%d register Line: %d Param: %d\n", - (par[i].val & 1), (par[i].val & 1), code_line, current_param); - else if (par[i].val >= 0x20 && par[i].val <= 0x21) - fprintf(stderr, "WARNING: $ACC%d register used instead of $ACM%d register Line: %d Param: %d\n", - (par[i].val & 1), (par[i].val & 1), code_line, current_param); - else - ShowError(ERR_WRONG_PARAMETER_ACC); - } - break; - - case P_ACCL: - if ((int)par[i].val < 0x1c || (int)par[i].val > 0x1d) - { - if (ext) fprintf(stderr, "(ext) "); - if (par[i].val >= 0x1e && par[i].val <= 0x1f) - { - fprintf(stderr, "%s ", cur_line.c_str()); - fprintf(stderr, "WARNING: $ACM%d register used instead of $ACL%d register Line: %d Param: %d\n", - (par[i].val & 1), (par[i].val & 1), code_line, current_param); - } - else if (par[i].val >= 0x20 && par[i].val <= 0x21) { - fprintf(stderr, "%s ", cur_line.c_str()); - fprintf(stderr, "WARNING: $ACC%d register used instead of $ACL%d register Line: %d Param: %d\n", - (par[i].val & 1), (par[i].val & 1), code_line, current_param); - } - else - ShowError(ERR_WRONG_PARAMETER_ACC); - } - break; -/* case P_ACCM_D: //P_ACC_MID: - if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f) - { - ShowError(ERR_WRONG_PARAMETER_MID_ACC); - } - break;*/ - } - continue; - } - - switch (par[i].type & (P_REG | 7)) - { - case P_REG: - if (ext) fprintf(stderr, "(ext) "); - ShowError(ERR_EXPECTED_PARAM_REG); - break; - case P_MEM: - if (ext) fprintf(stderr, "(ext) "); - ShowError(ERR_EXPECTED_PARAM_MEM); - break; - case P_VAL: - if (ext) fprintf(stderr, "(ext) "); - ShowError(ERR_EXPECTED_PARAM_VAL); - break; - case P_IMM: - if (ext) fprintf(stderr, "(ext) "); - ShowError(ERR_EXPECTED_PARAM_IMM); - break; - } - ShowError(ERR_WRONG_PARAMETER); - break; - } - else if ((opc->params[i].type & 3) != 0 && (par[i].type & 3) != 0) - { - // modified by Hermes: test NUMBER range - int value = get_mask_shifted_down(opc->params[i].mask); - unsigned int valueu = 0xffff & ~(value >> 1); - if ((int)par[i].val < 0) - { - if (value == 7) // value 7 por sbclr/sbset - { - fprintf(stderr,"Value must be from 0x0 to 0x%x\n", value); - ShowError(ERR_OUT_RANGE_NUMBER); - } - else if (opc->params[i].type == P_MEM) - { - if (value < 256) - fprintf(stderr, "Address value must be from 0x%x to 0x%x\n",valueu, (value>>1)); - else - fprintf(stderr, "Address value must be from 0x0 to 0x%x\n", value); - - ShowError(ERR_OUT_RANGE_NUMBER); - } - else if ((int)par[i].val < -((value >> 1) + 1)) - { - if (value < 128) - fprintf(stderr, "Value must be from -0x%x to 0x%x, is %i\n", - (value >> 1) + 1, value >> 1, par[i].val); - else - fprintf(stderr, "Value must be from -0x%x to 0x%x or 0x0 to 0x%x, is %i\n", - (value >> 1) + 1, value >> 1, value, par[i].val); - - ShowError(ERR_OUT_RANGE_NUMBER); - } - } - else - { - if (value == 7) // value 7 por sbclr/sbset - { - if (par[i].val > (unsigned)value) - { - fprintf(stderr,"Value must be from 0x%x to 0x%x, is %i\n",valueu, value, par[i].val); - ShowError(ERR_OUT_RANGE_NUMBER); - } - } - else if (opc->params[i].type == P_MEM) - { - if (value < 256) - value >>= 1; // addressing 8 bit with sign - if (par[i].val > (unsigned)value && - (par[i].val < valueu || par[i].val > (unsigned)0xffff)) - { - if (value < 256) - fprintf(stderr,"Address value must be from 0x%x to 0x%x, is %04x\n", valueu, value, par[i].val); - else - fprintf(stderr,"Address value must be minor of 0x%x\n", value+1); - ShowError(ERR_OUT_RANGE_NUMBER); - } - } - else - { - if (value < 128) - value >>= 1; // special case ASL/ASR/LSL/LSR - if (par[i].val > (unsigned)value) - { - if (value < 64) - fprintf(stderr,"Value must be from -0x%x to 0x%x, is %i\n", (value + 1), value, par[i].val); - else - fprintf(stderr,"Value must be minor of 0x%x, is %i\n", value + 1, par[i].val); - ShowError(ERR_OUT_RANGE_NUMBER); - } - } - } - continue; - } - } - m_current_param = 0; - return true; -} - - -// Merge opcode with params. -void DSPAssembler::BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf) -{ - outbuf[m_cur_addr] |= opc->opcode; - for (u32 i = 0; i < par_count; i++) - { - // Ignore the "reverse" parameters since they are implicit. - if (opc->params[i].type != P_ACC_D && opc->params[i].type != P_ACCM_D) - { - u16 t16 = outbuf[m_cur_addr + opc->params[i].loc]; - u16 v16 = par[i].val; - if (opc->params[i].lshift > 0) - v16 <<= opc->params[i].lshift; - else - v16 >>= -opc->params[i].lshift; - v16 &= opc->params[i].mask; - outbuf[m_cur_addr + opc->params[i].loc] = t16 | v16; - } - } -} - -void DSPAssembler::InitPass(int pass) -{ - failed = false; - if (pass == 1) - { - // Reset label table. Pre-populate with hw addresses and registers. - labels.Clear(); - labels.RegisterDefaults(); - aliases.clear(); - aliases["S15"] = "SET15"; - aliases["S16"] = "SET16"; - aliases["S40"] = "SET40"; - } - m_cur_addr = 0; - m_totalSize = 0; - cur_segment = SEGMENT_CODE; - segment_addr[SEGMENT_CODE] = 0; - segment_addr[SEGMENT_DATA] = 0; - segment_addr[SEGMENT_OVERLAY] = 0; -} - -bool DSPAssembler::AssembleFile(const char *fname, int pass) -{ - int disable_text = 0; // modified by Hermes - - std::ifstream fsrc(fname); - - if (fsrc.fail()) - { - std::cerr << "Cannot open file " << fname << std::endl; - return false; - } - - //printf("%s: Pass %d\n", fname, pass); - code_line = 0; - m_cur_pass = pass; - -#define LINEBUF_SIZE 1024 - char line[LINEBUF_SIZE] = {0}; - while (!failed && !fsrc.fail() && !fsrc.eof()) - { - int opcode_size = 0; - fsrc.getline(line, LINEBUF_SIZE); - if(fsrc.fail()) - break; - - cur_line = line; - //printf("A: %s\n", line); - code_line++; - - param_t params[10] = {{0}}; - param_t params_ext[10] = {{0}}; - - bool upper = true; - for (int i = 0; i < LINEBUF_SIZE; i++) - { - char c = line[i]; - // This stuff handles /**/ and // comments. - // modified by Hermes : added // and /* */ for long commentaries - if (c == '/') - { - if (i < 1023) - { - if (line[i+1] == '/') - c = 0x00; - else if (line[i+1] == '*') - { - // toggle comment mode. - disable_text = !disable_text; - } - } - } - else if (c == '*') - { - if (i < 1023 && line[i+1] == '/' && disable_text) - { - disable_text = 0; - c = 32; - line[i + 1] = 32; - } - } - - // turn text into spaces if disable_text is on (in a comment). - if (disable_text && ((unsigned char)c) > 32) c = 32; - - if (c == 0x0a || c == 0x0d || c == ';') - c = 0x00; - if (c == 0x09) // tabs to spaces - c = ' '; - if (c == '"') - upper = !upper; - if (upper && c >= 'a' && c <= 'z') // convert to uppercase - c = c - 'a' + 'A'; - line[i] = c; - if (c == 0) - break; // modified by Hermes - } - char *ptr = line; - - std::string label; - - size_t col_pos = std::string(line).find(":"); - if (col_pos != std::string::npos) - { - bool valid = true; - - for(int j = 0; j < (int)col_pos; j++) - { - if (j == 0) - if (!((ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_'))) - valid = false; - if (!((ptr[j] >= '0' && ptr[j] <= '9') || (ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_'))) - valid = false; - } - if (valid) - { - label = std::string(line).substr(0, col_pos); - ptr += col_pos + 1; - } - } - - char *opcode = NULL; - opcode = strtok(ptr, " "); - char *opcode_ext = NULL; - - u32 params_count = 0; - u32 params_count_ext = 0; - if (opcode) - { - if ((opcode_ext = strstr(opcode, "'")) != NULL) - { - opcode_ext[0] = '\0'; - opcode_ext++; - if (strlen(opcode_ext) == 0) - opcode_ext = NULL; - } - // now we have opcode and label - - params_count = 0; - params_count_ext = 0; - - char *paramstr = strtok(NULL, "\0"); - char *paramstr_ext = 0; - // there is valid opcode so probably we have parameters - - if (paramstr) - { - if ((paramstr_ext = strstr(paramstr, ":")) != NULL) - { - paramstr_ext[0] = '\0'; - paramstr_ext++; - } - } - - if (paramstr) - params_count = GetParams(paramstr, params); - if (paramstr_ext) - params_count_ext = GetParams(paramstr_ext, params_ext); - } - - if (!label.empty()) - { - // there is a valid label so lets store it in labels table - u32 lval = m_cur_addr; - if (opcode) - { - if (strcmp(opcode, "EQU") == 0) - { - lval = params[0].val; - opcode = NULL; - } - } - if (pass == 1) - labels.RegisterLabel(label, lval); - } - - if (opcode == NULL) - continue; - - // check if opcode is reserved compiler word - if (strcmp("INCLUDE", opcode) == 0) - { - if (params[0].type == P_STR) - { - char *tmpstr; - u32 thisCodeline = code_line; - - if (include_dir.size()) - { - tmpstr = (char *)malloc(include_dir.size() + strlen(params[0].str) + 2); - sprintf(tmpstr, "%s/%s", include_dir.c_str(), params[0].str); - } - else - { - tmpstr = (char *)malloc(strlen(params[0].str) + 1); - strcpy(tmpstr, params[0].str); - } - - AssembleFile(tmpstr, pass); - - code_line = thisCodeline; - - free(tmpstr); - } - else - ShowError(ERR_EXPECTED_PARAM_STR); - continue; - } - - if (strcmp("INCDIR", opcode) == 0) - { - if (params[0].type == P_STR) - include_dir = params[0].str; - else - ShowError(ERR_EXPECTED_PARAM_STR); - continue; - } - - if (strcmp("ORG", opcode) == 0) - { - if (params[0].type == P_VAL) - m_cur_addr = params[0].val; - else - ShowError(ERR_EXPECTED_PARAM_VAL); - continue; - } - - if (strcmp("SEGMENT", opcode) == 0) - { - if (params[0].type == P_STR) - { - segment_addr[cur_segment] = m_cur_addr; - if (strcmp("DATA", params[0].str) == 0) - cur_segment = SEGMENT_DATA; - if (strcmp("CODE", params[0].str) == 0) - cur_segment = SEGMENT_CODE; - m_cur_addr = segment_addr[cur_segment]; - } - else - ShowError(ERR_EXPECTED_PARAM_STR); - continue; - } - - const opc_t *opc = FindOpcode(opcode, params_count, opcodes, opcodes_size); - if (!opc) - opc = &cw; - - opcode_size = opc->size; - - VerifyParams(opc, params, params_count); - - const opc_t *opc_ext = NULL; - // Check for opcode extensions. - if (opc->extended) - { - if (opcode_ext) - { - opc_ext = FindOpcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size); - VerifyParams(opc_ext, params_ext, params_count_ext, true); - } - else if (params_count_ext) - ShowError(ERR_EXT_PAR_NOT_EXT); - } - else - { - if (opcode_ext) - ShowError(ERR_EXT_CANT_EXTEND_OPCODE); - if (params_count_ext) - ShowError(ERR_EXT_PAR_NOT_EXT); - } - - if (pass == 2) - { - // generate binary - ((u16 *)gdg_buffer)[m_cur_addr] = 0x0000; - BuildCode(opc, params, params_count, (u16 *)gdg_buffer); - if (opc_ext) - BuildCode(opc_ext, params_ext, params_count_ext, (u16 *)gdg_buffer); - } - - m_cur_addr += opcode_size; - m_totalSize += opcode_size; - }; - - if (!failed) - fsrc.close(); - - return !failed; -} diff --git a/Source/Core/DSPCore/Src/assemble.h b/Source/Core/DSPCore/Src/assemble.h deleted file mode 100644 index f140d0e69e..0000000000 --- a/Source/Core/DSPCore/Src/assemble.h +++ /dev/null @@ -1,139 +0,0 @@ -/*==================================================================== - - 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 diff --git a/Source/Core/DSPCore/Src/disassemble.cpp b/Source/Core/DSPCore/Src/disassemble.cpp deleted file mode 100644 index 03a81ddb1a..0000000000 --- a/Source/Core/DSPCore/Src/disassemble.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/*==================================================================== - - filename: disassemble.cpp - 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. - - ====================================================================*/ - -#include <stdio.h> -#include <stdlib.h> - -#include "Common.h" -#include "FileUtil.h" -#include "disassemble.h" -#include "DSPTables.h" - -#ifdef _MSC_VER -#pragma warning(disable:4996) -#endif - -#ifndef MAX_PATH -#include <Windows.h> // For MAX_PATH -#endif - -extern void nop(const UDSPInstruction opc); - -DSPDisassembler::DSPDisassembler(const AssemblerSettings &settings) - : settings_(settings) -{ -} - -DSPDisassembler::~DSPDisassembler() -{ - // Some old code for logging unknown ops. - char filename[MAX_PATH]; - sprintf(filename, "%sUnkOps.txt", File::GetUserPath(D_DUMPDSP_IDX)); - FILE *uo = fopen(filename, "w"); - if (!uo) - return; - - int count = 0; - for (std::map<u16, int>::const_iterator iter = unk_opcodes.begin(); - iter != unk_opcodes.end(); ++iter) - { - if (iter->second > 0) - { - count++; - fprintf(uo, "OP%04x\t%d", iter->first, iter->second); - for (int j = 15; j >= 0; j--) // print op bits - { - if ((j & 0x3) == 3) - fprintf(uo, "\tb"); - fprintf(uo, "%d", (iter->first >> j) & 0x1); - } - fprintf(uo, "\n"); - } - } - fprintf(uo, "Unknown opcodes count: %d\n", count); - fclose(uo); -} - -bool DSPDisassembler::Disassemble(int start_pc, const std::vector<u16> &code, int base_addr, std::string &text) -{ - const char *tmp1 = "tmp1.bin"; - - // First we have to dump the code to a bin file. - FILE *f = fopen(tmp1, "wb"); - fwrite(&code[0], 1, code.size() * 2, f); - fclose(f); - - // Run the two passes. - return DisFile(tmp1, base_addr, 1, text) && DisFile(tmp1, base_addr, 2, text); -} - -char *DSPDisassembler::DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, char *strbuf) -{ - char *buf = strbuf; - for (int j = 0; j < opc.param_count; j++) - { - if (j > 0) - buf += sprintf(buf, ", "); - - u32 val = (opc.params[j].loc >= 1) ? op2 : op1; - val &= opc.params[j].mask; - if (opc.params[j].lshift < 0) - val = val << (-opc.params[j].lshift); - else - val = val >> opc.params[j].lshift; - - u32 type = opc.params[j].type; - if ((type & 0xff) == 0x10) - type &= 0xff00; - - if (type & P_REG) - { - // Check for _D parameter - if so flip. - if ((type == P_ACC_D) || (type == P_ACCM_D)) // Used to be P_ACCM_D TODO verify - val = (~val & 0x1) | ((type & P_REGS_MASK) >> 8); - else - val |= (type & P_REGS_MASK) >> 8; - type &= ~P_REGS_MASK; - } - - switch (type) - { - case P_REG: - if (settings_.decode_registers) - sprintf(buf, "$%s", pdregname(val)); - else - sprintf(buf, "$%d", val); - break; - - case P_PRG: - if (settings_.decode_registers) - sprintf(buf, "@$%s", pdregname(val)); - else - sprintf(buf, "@$%d", val); - break; - - case P_VAL: - case P_ADDR_I: - case P_ADDR_D: - if (settings_.decode_names) - { - sprintf(buf, "%s", pdname(val)); - } - else - sprintf(buf, "0x%04x", val); - break; - - case P_IMM: - if (opc.params[j].size != 2) - { - if (opc.params[j].mask == 0x003f) // LSL, LSR, ASL, ASR - sprintf(buf, "#%d", (val & 0x20) ? (val | 0xFFFFFFC0) : val); // 6-bit sign extension - else - sprintf(buf, "#0x%02x", val); - } - else - { - sprintf(buf, "#0x%04x", val); - } - break; - - case P_MEM: - if (opc.params[j].size != 2) - val = (u16)(s16)(s8)val; - - if (settings_.decode_names) - sprintf(buf, "@%s", pdname(val)); - else - sprintf(buf, "@0x%04x", val); - break; - - default: - ERROR_LOG(DSPLLE, "Unknown parameter type: %x", opc.params[j].type); - break; - } - - buf += strlen(buf); - } - - return strbuf; -} - -static void MakeLowerCase(char *ptr) -{ - int i = 0; - while (ptr[i]) - { - ptr[i] = tolower(ptr[i]); - i++; - } -} - -bool DSPDisassembler::DisOpcode(const u16 *binbuf, int base_addr, int pass, u16 *pc, std::string &dest) -{ - char buffer[256]; - char *buf = buffer; - - // Start with 8 spaces, if there's no label. - buf[0] = ' '; - buf[1] = '\0'; - buf++; - - if ((*pc & 0x7fff) >= 0x1000) - { - ++pc; - dest.append("; outside memory"); - return false; - } - - const u32 op1 = binbuf[*pc & 0x0fff]; - - const DSPOPCTemplate *opc = NULL; - const DSPOPCTemplate *opc_ext = NULL; - - // find opcode - for (int j = 0; j < opcodes_size; j++) - { - u16 mask = opcodes[j].opcode_mask; - - if ((op1 & mask) == opcodes[j].opcode) - { - opc = &opcodes[j]; - break; - } - } - const DSPOPCTemplate fake_op = {"CW", 0x0000, 0x0000, nop, NULL, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false}; - if (!opc) - opc = &fake_op; - - bool extended = false; - bool only7bitext = false; - - if (((opc->opcode >> 12) == 0x3) && (op1 & 0x007f)) { - extended = true; - only7bitext = true; - } - else if (((opc->opcode >> 12) > 0x3) && (op1 & 0x00ff)) - extended = true; - else - extended = false; - - if (extended) - { - // opcode has an extension - // find opcode - for (int j = 0; j < opcodes_ext_size; j++) - { - if (only7bitext) { - if (((op1 & 0x7f) & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) - { - opc_ext = &opcodes_ext[j]; - break; - } - } - else { - if ((op1 & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) - { - opc_ext = &opcodes_ext[j]; - break; - } - } - } - } - - // printing - - if (settings_.show_pc) - buf += sprintf(buf, "%04x ", *pc); - - u32 op2; - - // Size 2 - the op has a large immediate. - if (opc->size == 2) - { - op2 = binbuf[(*pc + 1) & 0x0fff]; - if (settings_.show_hex) - buf += sprintf(buf, "%04x %04x ", op1, op2); - } - else - { - op2 = 0; - if (settings_.show_hex) - buf += sprintf(buf, "%04x ", op1); - } - - char opname[20]; - strcpy(opname, opc->name); - if (settings_.lower_case_ops) - MakeLowerCase(opname); - char ext_buf[20]; - if (extended) - sprintf(ext_buf, "%s%c%s", opname, settings_.ext_separator, opc_ext->name); - else - sprintf(ext_buf, "%s", opname); - if (settings_.lower_case_ops) - MakeLowerCase(ext_buf); - - if (settings_.print_tabs) - buf += sprintf(buf, "%s\t", ext_buf); - else - buf += sprintf(buf, "%-12s", ext_buf); - - if (opc->param_count > 0) - DisParams(*opc, op1, op2, buf); - - buf += strlen(buf); - - // Handle opcode extension. - if (extended) - { - if (opc->param_count > 0) - buf += sprintf(buf, " "); - buf += sprintf(buf, ": "); - if (opc_ext->param_count > 0) - DisParams(*opc_ext, op1, op2, buf); - - buf += strlen(buf); - } - - if (opc->opcode_mask == 0) - { - // unknown opcode - unk_opcodes[op1]++; - sprintf(buf, "\t\t; *** UNKNOWN OPCODE ***"); - } - - if (extended) - *pc += opc_ext->size; - else - *pc += opc->size; - - if (pass == 2) - dest.append(buffer); - return true; -} - -bool DSPDisassembler::DisFile(const char* name, int base_addr, int pass, std::string &output) -{ - FILE* in = fopen(name, "rb"); - if (in == NULL) - { - printf("gd_dis_file: No input\n"); - return false; - } - - int size = (int)File::GetSize(in) & ~1; - u16 *binbuf = new u16[size / 2]; - fread(binbuf, 1, size, in); - fclose(in); - - // Actually do the disassembly. - for (u16 pc = 0; pc < (size / 2);) - { - DisOpcode(binbuf, base_addr, pass, &pc, output); - if (pass == 2) - output.append("\n"); - } - delete [] binbuf; - return true; -} diff --git a/Source/Core/DSPCore/Src/disassemble.h b/Source/Core/DSPCore/Src/disassemble.h deleted file mode 100644 index dba9f36287..0000000000 --- a/Source/Core/DSPCore/Src/disassemble.h +++ /dev/null @@ -1,87 +0,0 @@ -/*==================================================================== - - 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_DISASSEMBLE_H -#define _DSP_DISASSEMBLE_H - -#include <map> -#include <vector> - -#include "Common.h" -#include "DSPTables.h" -#include "LabelMap.h" - -struct AssemblerSettings -{ - AssemblerSettings() - : print_tabs(false), - show_hex(false), - show_pc(false), - force(false), - decode_names(true), - decode_registers(true), - ext_separator('\''), - lower_case_ops(true), - pc(0) - { - } - - bool print_tabs; - bool show_hex; - bool show_pc; - bool force; - bool decode_names; - bool decode_registers; - char ext_separator; - bool lower_case_ops; - - u16 pc; -}; - -class DSPDisassembler -{ -public: - DSPDisassembler(const AssemblerSettings &settings); - ~DSPDisassembler(); - - bool Disassemble(int start_pc, const std::vector<u16> &code, int base_addr, std::string &text); - - // Warning - this one is trickier to use right. - // Use pass == 2 if you're just using it by itself. - bool DisOpcode(const u16 *binbuf, int base_addr, int pass, u16 *pc, std::string &dest); - -private: - // Moves PC forward and writes the result to dest. - bool DisFile(const char* name, int base_addr, int pass, std::string &output); - - char* DisParams(const DSPOPCTemplate& opc, u16 op1, u16 op2, char* strbuf); - std::map<u16, int> unk_opcodes; - - const AssemblerSettings settings_; - - LabelMap labels; -}; - -#endif // _DSP_DISASSEMBLE_H - |
