JitCommon: Signed 32-bit division magic constants
Add a function to calculate the magic constants required to optimize signed 32-bit division. Since this optimization is not exclusive to any particular architecture, JitCommon seemed like a good place to put this.
This commit is contained in:
parent
c9adc60d73
commit
5bb8798df6
|
@ -430,6 +430,8 @@ add_library(core
|
||||||
PowerPC/Interpreter/Interpreter_Tables.cpp
|
PowerPC/Interpreter/Interpreter_Tables.cpp
|
||||||
PowerPC/Interpreter/Interpreter.cpp
|
PowerPC/Interpreter/Interpreter.cpp
|
||||||
PowerPC/Interpreter/Interpreter.h
|
PowerPC/Interpreter/Interpreter.h
|
||||||
|
PowerPC/JitCommon/DivUtils.cpp
|
||||||
|
PowerPC/JitCommon/DivUtils.h
|
||||||
PowerPC/JitCommon/JitAsmCommon.cpp
|
PowerPC/JitCommon/JitAsmCommon.cpp
|
||||||
PowerPC/JitCommon/JitAsmCommon.h
|
PowerPC/JitCommon/JitAsmCommon.h
|
||||||
PowerPC/JitCommon/JitBase.cpp
|
PowerPC/JitCommon/JitBase.cpp
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright 2021 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "Core/PowerPC/JitCommon/DivUtils.h"
|
||||||
|
|
||||||
|
namespace JitCommon
|
||||||
|
{
|
||||||
|
Magic SignedDivisionConstants(s32 d)
|
||||||
|
{
|
||||||
|
const u32 two31 = 2147483648;
|
||||||
|
|
||||||
|
const u32 ad = std::abs(d);
|
||||||
|
const u32 t = two31 - (d < 0);
|
||||||
|
const u32 anc = t - 1 - t % ad;
|
||||||
|
u32 q1 = two31 / anc;
|
||||||
|
u32 r1 = two31 - q1 * anc;
|
||||||
|
u32 q2 = two31 / ad;
|
||||||
|
u32 r2 = two31 - q2 * ad;
|
||||||
|
|
||||||
|
s32 p = 31;
|
||||||
|
u32 delta;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
|
||||||
|
q1 *= 2;
|
||||||
|
r1 *= 2;
|
||||||
|
if (r1 >= anc)
|
||||||
|
{
|
||||||
|
q1++;
|
||||||
|
r1 -= anc;
|
||||||
|
}
|
||||||
|
|
||||||
|
q2 *= 2;
|
||||||
|
r2 *= 2;
|
||||||
|
if (r2 >= ad)
|
||||||
|
{
|
||||||
|
q2++;
|
||||||
|
r2 -= ad;
|
||||||
|
}
|
||||||
|
delta = ad - r2;
|
||||||
|
} while (q1 < delta || (q1 == delta && r1 == 0));
|
||||||
|
|
||||||
|
Magic mag;
|
||||||
|
mag.multiplier = q2 + 1;
|
||||||
|
if (d < 0)
|
||||||
|
mag.multiplier = -mag.multiplier;
|
||||||
|
mag.shift = p - 32;
|
||||||
|
|
||||||
|
return mag;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace JitCommon
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2021 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
namespace JitCommon
|
||||||
|
{
|
||||||
|
struct Magic
|
||||||
|
{
|
||||||
|
s32 multiplier;
|
||||||
|
u8 shift;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate the constants required to optimize a signed 32-bit integer division.
|
||||||
|
// Taken from The PowerPC Compiler Writer's Guide and LLVM.
|
||||||
|
// Divisor must not be -1, 0, and 1.
|
||||||
|
Magic SignedDivisionConstants(s32 divisor);
|
||||||
|
|
||||||
|
} // namespace JitCommon
|
|
@ -27,6 +27,12 @@
|
||||||
<Project>{41279555-f94f-4ebc-99de-af863c10c5c4}</Project>
|
<Project>{41279555-f94f-4ebc-99de-af863c10c5c4}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Core\PowerPC\JitCommon\DivUtils.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Core\PowerPC\JitCommon\DivUtils.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets" />
|
<ImportGroup Label="ExtensionTargets" />
|
||||||
</Project>
|
</Project>
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright 2021 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "Core/PowerPC/JitCommon/DivUtils.h"
|
||||||
|
|
||||||
|
using namespace JitCommon;
|
||||||
|
|
||||||
|
TEST(DivUtils, Signed)
|
||||||
|
{
|
||||||
|
Magic m3 = SignedDivisionConstants(3);
|
||||||
|
Magic m5 = SignedDivisionConstants(5);
|
||||||
|
Magic m7 = SignedDivisionConstants(7);
|
||||||
|
Magic minus3 = SignedDivisionConstants(-3);
|
||||||
|
Magic minus5 = SignedDivisionConstants(-5);
|
||||||
|
Magic minus7 = SignedDivisionConstants(-7);
|
||||||
|
|
||||||
|
EXPECT_EQ(0x55555556, m3.multiplier);
|
||||||
|
EXPECT_EQ(0, m3.shift);
|
||||||
|
EXPECT_EQ(0x66666667, m5.multiplier);
|
||||||
|
EXPECT_EQ(1, m5.shift);
|
||||||
|
EXPECT_EQ(-0x6DB6DB6D, m7.multiplier);
|
||||||
|
EXPECT_EQ(2, m7.shift);
|
||||||
|
|
||||||
|
EXPECT_EQ(-0x55555556, minus3.multiplier);
|
||||||
|
EXPECT_EQ(0, minus3.shift);
|
||||||
|
EXPECT_EQ(-0x66666667, minus5.multiplier);
|
||||||
|
EXPECT_EQ(1, minus5.shift);
|
||||||
|
EXPECT_EQ(0x6DB6DB6D, minus7.multiplier);
|
||||||
|
EXPECT_EQ(2, minus7.shift);
|
||||||
|
}
|
|
@ -68,6 +68,7 @@
|
||||||
<ClCompile Include="Core\IOS\FS\FileSystemTest.cpp" />
|
<ClCompile Include="Core\IOS\FS\FileSystemTest.cpp" />
|
||||||
<ClCompile Include="Core\MMIOTest.cpp" />
|
<ClCompile Include="Core\MMIOTest.cpp" />
|
||||||
<ClCompile Include="Core\PageFaultTest.cpp" />
|
<ClCompile Include="Core\PageFaultTest.cpp" />
|
||||||
|
<ClCompile Include="DivUtilsTest.cpp" />
|
||||||
<ClCompile Include="FileUtil.cpp" />
|
<ClCompile Include="FileUtil.cpp" />
|
||||||
<ClCompile Include="VideoCommon\VertexLoaderTest.cpp" />
|
<ClCompile Include="VideoCommon\VertexLoaderTest.cpp" />
|
||||||
<ClCompile Include="StubHost.cpp" />
|
<ClCompile Include="StubHost.cpp" />
|
||||||
|
|
Loading…
Reference in New Issue