GCC port and new defines for new ARM port (#294)

* Put SSE code under HAVE_SSE define

* Fix circular dependency on GCC 7.3

* Provide a way to disable AMXX related hacks, when it's not needed

* Fix ASM inline for GCC

* Fix compiling with MSVC

* Fix compiling with MSVC and ICC

* Check for HAVE_SSE in sse_mathfun.cpp after including precompiled, so SSE state will be determined

* Better check for SSE availability

* Missing call ::ClientCommand_
Make CSaveRestoreBuffer::m_Sizes as const
Cosmetic changes

* Gradle: Add GCC Toolchain

* GCC: Fix compile

* Gradle: Add -fno-devirtualize to compiler flags for GCC
This commit is contained in:
Alibek Omarov 2018-05-20 18:28:03 +03:00 committed by Dmitry Novikov
parent fe0ea9a1bc
commit 2b4eb6c137
15 changed files with 157 additions and 44 deletions

View File

@ -24,6 +24,7 @@ import org.apache.commons.compress.archivers.ArchiveInputStream
apply plugin: 'cpp'
apply plugin: IccCompilerPlugin
apply plugin: GccCompilerPlugin
apply plugin: RegamedllPlayTestPlugin
apply plugin: gradlecpp.CppUnitTestPlugin
@ -59,11 +60,11 @@ void createIntergrationTestTask(NativeBinarySpec b) {
testDemos = project.configurations.regamedll_tests
testFor = b
//inputs/outputs for up-to-date check
// inputs/outputs for up-to-date check
inputs.files testDemos.files
outputs.dir regamedllTestLogs
//dependencies on test executable
// dependencies on test executable
if (unitTestTask) {
dependsOn unitTestTask
}
@ -90,6 +91,7 @@ void postEvaluate(NativeBinarySpec b) {
void setupToolchain(NativeBinarySpec b)
{
boolean useGcc = project.hasProperty("useGcc")
boolean unitTestExecutable = b.component.name.endsWith('_tests')
boolean regamedllFixes = b.flavor.name.contains('regamedllFixes')
@ -127,10 +129,13 @@ void setupToolchain(NativeBinarySpec b)
}
else if (cfg instanceof GccToolchainConfig)
{
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
enabled: true,
pchSourceSet: 'regamedll_pch'
);
if (!useGcc)
{
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
enabled: true,
pchSourceSet: 'regamedll_pch'
);
}
cfg.compilerOptions.languageStandard = 'c++14'
cfg.defines([
@ -145,8 +150,22 @@ void setupToolchain(NativeBinarySpec b)
'_access' : 'access'
])
cfg.linkerOptions.args '-no-opt-class-analysis'
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-g0', '-fno-rtti', '-fno-exceptions'
if (useGcc) {
// Produce code optimized for the most common IA32/AMD64/EM64T processors.
// As new processors are deployed in the marketplace, the behavior of this option will change.
cfg.compilerOptions.args '-mtune=generic', '-msse3', '-Wno-write-strings', '-Wno-invalid-offsetof', '-fpermissive', '-fno-devirtualize'
} else {
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp'
// Not use c++ class hierarchy for analyze and resolve C++ virtual function calls at compile time.
//
// Example issue:
// Expected: FF .. call dword ptr + offset, pEntity->Spawn();
// Got: E8 .. call CBaseEntity::Spawn();
cfg.linkerOptions.args '-qno-opt-class-analysis'
}
cfg.compilerOptions.args '-g0', '-fno-rtti', '-fno-exceptions'
cfg.projectLibpath(project, '/lib/linux32')
cfg.extraLibs 'dl', 'm', 'stdc++', 'aelf32'
}
@ -243,7 +262,10 @@ model {
toolChains {
visualCpp(VisualCpp) {
}
icc(Icc) {
if (project.hasProperty("useGcc")) {
gcc(Gcc)
} else {
icc(Icc)
}
}

View File

@ -29,7 +29,7 @@
#pragma once
#ifdef PLAY_GAMEDLL
// NOTE: In some cases we need high precision of floating-point,
// NOTE: In some cases we need high precision of floating-point,
// so use double instead of float, otherwise unittest will fail
typedef double real_t;
#else
@ -85,6 +85,7 @@ const T& clamp(const T& a, const T& min, const T& max) { return (a > max) ? max
#define clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
#endif // __cplusplus
#ifdef HAVE_SSE
inline float M_sqrt(float value) {
return _mm_cvtss_f32(_mm_sqrt_ss(_mm_load_ss(&value)));
}
@ -93,12 +94,14 @@ inline double M_sqrt(double value) {
auto v = _mm_load_sd(&value);
return _mm_cvtsd_f64(_mm_sqrt_sd(v, v));
}
#endif
template<typename T>
inline double M_sqrt(T value) {
return sqrt(value);
}
#ifdef HAVE_SSE
inline float M_min(float a, float b) {
return _mm_cvtss_f32(_mm_min_ss(_mm_load_ss(&a), _mm_load_ss(&b)));
}
@ -106,12 +109,14 @@ inline float M_min(float a, float b) {
inline double M_min(double a, double b) {
return _mm_cvtsd_f64(_mm_min_sd(_mm_load_sd(&a), _mm_load_sd(&b)));
}
#endif
template<typename T>
inline T M_min(T a, T b) {
return min(a, b);
}
#ifdef HAVE_SSE
inline float M_max(float a, float b) {
return _mm_cvtss_f32(_mm_max_ss(_mm_load_ss(&a), _mm_load_ss(&b)));
}
@ -119,12 +124,14 @@ inline float M_max(float a, float b) {
inline double M_max(double a, double b) {
return _mm_cvtsd_f64(_mm_max_sd(_mm_load_sd(&a), _mm_load_sd(&b)));
}
#endif
template<typename T>
inline T M_max(T a, T b) {
return max(a, b);
}
#ifdef HAVE_SSE
inline float M_clamp(float a, float min, float max) {
return _mm_cvtss_f32(_mm_min_ss(_mm_max_ss(_mm_load_ss(&a), _mm_load_ss(&min)), _mm_load_ss(&max)));
}
@ -132,6 +139,7 @@ inline float M_clamp(float a, float min, float max) {
inline double M_clamp(double a, double min, double max) {
return _mm_cvtsd_f64(_mm_min_sd(_mm_max_sd(_mm_load_sd(&a), _mm_load_sd(&min)), _mm_load_sd(&max)));
}
#endif
template<typename T>
inline T M_clamp(T a, T min, T max) {

View File

@ -527,7 +527,7 @@ C_DLLEXPORT int Server_GetBlendingInterface(int version, struct sv_blending_inte
return 1;
}
#ifdef REGAMEDLL_FIXES // SSE2 version
#if defined(REGAMEDLL_FIXES) && defined(HAVE_SSE) // SSE2 version
void AngleQuaternion(vec_t *angles, vec_t *quaternion)
{
static const ALIGN16_BEG size_t ps_signmask[4] ALIGN16_END = { 0x80000000, 0, 0x80000000, 0 };

View File

@ -8296,6 +8296,9 @@ void CBasePlayer::ClientCommand(const char *cmd, const char *arg1, const char *a
auto pEntity = ENT(pev);
#ifdef NO_AMXX_HACKS // a1ba: not needed for non-x86 port
::ClientCommand_(pEntity);
#else // NO_AMXX_HACKS
// NOTE: force __cdecl to allow cstrike amxx module to hook ClientCommand
#if defined _MSC_VER || defined __INTEL_COMPILER
__asm
@ -8307,13 +8310,13 @@ void CBasePlayer::ClientCommand(const char *cmd, const char *arg1, const char *a
#else
asm volatile (
"pushl %0\n\t"
"call %1\n\t"
"addl %%esp, $4\n\t"
::
"g" (pEntity),
"g" (ClientCommand_),
"call *%1\n\t"
"addl $4, %%esp\n\t"
: /* no outputs */
: "g" (pEntity), "g" (ClientCommand_)
);
#endif // _MSC_VER || defined __INTEL_COMPILER
#endif // NO_AMXX_HACKS
UseBotArgs = false;
}

View File

@ -160,6 +160,28 @@ void EntvarsKeyvalue(entvars_t *pev, KeyValueData *pkvd)
}
}
const int CSaveRestoreBuffer::m_Sizes[] =
{
sizeof(float), // FIELD_FLOAT
sizeof(int), // FIELD_STRING
sizeof(int), // FIELD_ENTITY
sizeof(int), // FIELD_CLASSPTR
sizeof(int), // FIELD_EHANDLE
sizeof(int), // FIELD_entvars_t
sizeof(int), // FIELD_EDICT
sizeof(float) * 3, // FIELD_VECTOR
sizeof(float) * 3, // FIELD_POSITION_VECTOR
sizeof(int *), // FIELD_POINTER
sizeof(int), // FIELD_INTEGER
sizeof(int *), // FIELD_FUNCTION
sizeof(int), // FIELD_BOOLEAN
sizeof(short), // FIELD_SHORT
sizeof(char), // FIELD_CHARACTER
sizeof(float), // FIELD_TIME
sizeof(int), // FIELD_MODELNAME
sizeof(int), // FIELD_SOUNDNAME
};
CSaveRestoreBuffer::CSaveRestoreBuffer()
{
m_pData = nullptr;

View File

@ -85,26 +85,7 @@ public:
unsigned short TokenHash(const char *pszToken);
protected:
static constexpr int m_Sizes[] = {
sizeof(float), // FIELD_FLOAT
sizeof(int), // FIELD_STRING
sizeof(int), // FIELD_ENTITY
sizeof(int), // FIELD_CLASSPTR
sizeof(int), // FIELD_EHANDLE
sizeof(int), // FIELD_entvars_t
sizeof(int), // FIELD_EDICT
sizeof(float) * 3, // FIELD_VECTOR
sizeof(float) * 3, // FIELD_POSITION_VECTOR
sizeof(int *), // FIELD_POINTER
sizeof(int), // FIELD_INTEGER
sizeof(int *), // FIELD_FUNCTION
sizeof(int), // FIELD_BOOLEAN
sizeof(short), // FIELD_SHORT
sizeof(char), // FIELD_CHARACTER
sizeof(float), // FIELD_TIME
sizeof(int), // FIELD_MODELNAME
sizeof(int), // FIELD_SOUNDNAME
};
static const int m_Sizes[];
SAVERESTOREDATA *m_pData;
void BufferRewind(int size);

View File

@ -323,7 +323,8 @@ inline T *UTIL_FindEntityInSphere(T *pStartEntity, const Vector &vecCenter, floa
pentEntity = FIND_ENTITY_IN_SPHERE(pentEntity, vecCenter, flRadius);
if (!FNullEnt(pentEntity))
{
return (T *)CBaseEntity::Instance(pentEntity);
// a1ba: can't use CBaseEntity::Instance here, because circular dependency in cbase.h
return GET_PRIVATE<T>(pentEntity);
}
return nullptr;

View File

@ -47,6 +47,12 @@
#include <deque>
#include <functional>
// enable SSE code only if it's enabled in compiler options
#if defined(__SSE__) || defined(__SSE2__) || defined(_M_IX86_FP) || defined(_M_AMD64) || defined(_M_X64)
// #error "SSE enabled"
#define HAVE_SSE
#endif
#ifdef _WIN32 // WINDOWS
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
@ -87,9 +93,10 @@
#include <fstream>
#include <iomanip>
#ifdef HAVE_SSE
#include <smmintrin.h>
#include <xmmintrin.h>
#endif // HAVE_SSE
#ifdef _WIN32 // WINDOWS
// Define __func__ on VS less than 2015
@ -97,6 +104,8 @@
#define __func__ __FUNCTION__
#endif
// We'll not use __func__ on windows because we want 'A::foo' instead of 'foo'
#define __FUNC__ __FUNCTION__
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
@ -151,6 +160,7 @@
typedef unsigned int UNINT32;
#define FASTCALL
#define __FUNC__ __func__
#define CDECL __attribute__ ((cdecl))
#define STDCALL __attribute__ ((stdcall))
#define HIDDEN __attribute__((visibility("hidden")))

View File

@ -49,11 +49,11 @@ bool AbstractHookChainRegistry::findHook(void* hookFunc) const
void AbstractHookChainRegistry::addHook(void* hookFunc, int priority)
{
if (!hookFunc) {
Sys_Error("%s: Parameter hookFunc can't be a nullptr", __func__);
Sys_Error("%s: Parameter hookFunc can't be a nullptr", __FUNC__);
}
if (findHook(hookFunc)) {
Sys_Error("%s: The same handler can't be used twice on the hookchain.", __func__);
Sys_Error("%s: The same handler can't be used twice on the hookchain.", __FUNC__);
}
for (auto i = 0; i < MAX_HOOKS_IN_CHAIN; i++)
@ -72,7 +72,7 @@ void AbstractHookChainRegistry::addHook(void* hookFunc, int priority)
}
if (m_NumHooks >= MAX_HOOKS_IN_CHAIN) {
Sys_Error("%s: MAX_HOOKS_IN_CHAIN limit hit", __func__);
Sys_Error("%s: MAX_HOOKS_IN_CHAIN limit hit", __FUNC__);
}
m_NumHooks++;

View File

@ -54,7 +54,7 @@ public:
IHookChainImpl(void** hooks, origfunc_t orig) : m_Hooks(hooks), m_OriginalFunc(orig)
{
if (orig == nullptr && !is_void(orig))
Sys_Error("%s: Non-void HookChain without original function.", __func__);
Sys_Error("%s: Non-void HookChain without original function.", __FUNC__);
}
virtual ~IHookChainImpl() {}
@ -90,7 +90,7 @@ public:
IHookChainClassImpl(void** hooks, origfunc_t orig) : m_Hooks(hooks), m_OriginalFunc(orig)
{
if (orig == nullptr && !is_void(orig))
Sys_Error("%s: Non-void HookChain without original function.", __func__);
Sys_Error("%s: Non-void HookChain without original function.", __FUNC__);
}
virtual ~IHookChainClassImpl() {}
@ -126,7 +126,7 @@ public:
IHookChainClassEmptyImpl(void** hooks, origfunc_t orig, t_class *object) : m_Hooks(hooks), m_OriginalFunc(orig), m_Object(object)
{
if (orig == nullptr && !is_void(orig))
Sys_Error("%s: Non-void HookChain without original function.", __func__);
Sys_Error("%s: Non-void HookChain without original function.", __FUNC__);
}
virtual ~IHookChainClassEmptyImpl() {}

View File

@ -34,7 +34,9 @@
#include "basetypes.h"
#include "archtypes.h"
#ifdef HAVE_SSE
#include "sse_mathfun.h"
#endif
#include "asmlib.h"
#include "MemPool.h"

View File

@ -31,6 +31,8 @@ misrepresented as being the original software.
#include "precompiled.h"
#ifdef HAVE_SSE
/* natural logarithm computed for 4 simultaneous float
return NaN for x <= 0
*/
@ -445,3 +447,4 @@ void sincos_ps(v4sf x, v4sf *s, v4sf *c) {
*s = _mm_xor_ps(xmm1, sign_bit_sin);
*c = _mm_xor_ps(xmm2, sign_bit_cos);
}
#endif // HAVE_SSE

View File

@ -8,6 +8,7 @@ import org.gradle.nativeplatform.toolchain.VisualCpp
apply from: 'shared_msvc.gradle'
apply from: 'shared_icc.gradle'
apply from: 'shared_gcc.gradle'
rootProject.ext.createToolchainConfig = { NativeBinarySpec bin ->
BinaryKind binaryKind
@ -37,6 +38,10 @@ rootProject.ext.createToolchainConfig = { NativeBinarySpec bin ->
{
return rootProject.createIccConfig(releaseBuild, binaryKind)
}
else if (bin.toolChain instanceof Gcc)
{
return rootProject.createGccConfig(releaseBuild, binaryKind)
}
else
{
throw new RuntimeException("Unknown native toolchain: ${bin.toolChain.class.name}")

55
shared_gcc.gradle Normal file
View File

@ -0,0 +1,55 @@
import org.doomedsociety.gradlecpp.cfg.BinaryKind
import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig
import org.doomedsociety.gradlecpp.gcc.OptimizationLevel
rootProject.ext.createGccConfig = { boolean release, BinaryKind binKind ->
GccToolchainConfig cfg
if (release) {
cfg = new GccToolchainConfig(
compilerOptions: new GccToolchainConfig.CompilerOptions(
optimizationLevel: OptimizationLevel.LEVEL_3,
stackProtector: false,
noBuiltIn: true,
positionIndependentCode: false,
extraDefines: [
'_GLIBCXX_USE_CXX11_ABI': 0,
]
),
linkerOptions: new GccToolchainConfig.LinkerOptions(
stripSymbolTable: false,
staticLibGcc: false,
staticLibStdCpp: false,
),
librarianOptions: new GccToolchainConfig.LibrarianOptions(
)
)
} else {
//debug
cfg = new GccToolchainConfig(
compilerOptions: new GccToolchainConfig.CompilerOptions(
optimizationLevel: OptimizationLevel.DISABLE,
stackProtector: true,
noBuiltIn: true,
extraDefines: [
'_GLIBCXX_USE_CXX11_ABI': 0,
]
),
linkerOptions: new GccToolchainConfig.LinkerOptions(
stripSymbolTable: false,
staticLibGcc: false,
staticLibStdCpp: false,
),
librarianOptions: new GccToolchainConfig.LibrarianOptions(
)
)
}
cfg.singleDefines('LINUX', '_LINUX')
return cfg
}

View File

@ -60,5 +60,6 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind ->
)
}
cfg.singleDefines('LINUX', '_LINUX')
return cfg
}