diff --git a/rehlds/engine/sv_main.cpp b/rehlds/engine/sv_main.cpp index bb0f6cb..a7a204d 100644 --- a/rehlds/engine/sv_main.cpp +++ b/rehlds/engine/sv_main.cpp @@ -470,11 +470,15 @@ qboolean SV_IsPlayerIndex(int index) return (index >= 1 && index <= g_psvs.maxclients); } -qboolean __declspec(naked) SV_IsPlayerIndex_wrapped(int index) +#if defined _MSC_VER || defined __INTEL_COMPILER +__declspec(naked) +#endif +qboolean SV_IsPlayerIndex_wrapped(int index) { // Original SV_IsPlayerIndex in swds.dll doesn't modify ecx nor edx. // During the compilation of original swds.dll compiler was assuming that these registers wouldn't be modified during call to SV_IsPlayerIndex(). // This is not true for code produced by msvc2013 (which uses ecx even in Release config). That's why we need a wrapper here that preserves ecx and edx before call to reversed SV_IsPlayerIndex(). +#if defined _MSC_VER || defined __INTEL_COMPILER __asm { mov eax, dword ptr[esp + 4]; @@ -487,6 +491,20 @@ qboolean __declspec(naked) SV_IsPlayerIndex_wrapped(int index) pop ecx; retn; } +#else + asm volatile ( + "pushl %%ecx\n\t" + "pushl %%edx\n\t" + "pushl %0\n\t" + "call $SV_IsPlayerIndex\n\t" + "addl %%esp, $4\n\t" + "popl %%edx\n\t" + "popl %%ecx\n\t" + "retn" + :: + "g" (index) + ); +#endif } /* ../engine/sv_main.c:514 */ @@ -5371,6 +5389,7 @@ void EXT_FUNC SV_WriteVoiceCodec_internal(sizebuf_t *pBuf) */ void __invokeValvesBuggedCreateBaseline(void* func, int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec_t* pmins, vec_t* pmaxs) { +#if defined _MSC_VER || defined __INTEL_COMPILER __asm { mov ecx, func push 0 @@ -5387,6 +5406,35 @@ void __invokeValvesBuggedCreateBaseline(void* func, int player, int eindex, stru call ecx add esp, 0x2C } +#else + asm volatile ( + "movl %%ecx, %0\n\t" + "pushl $0\n\t" + "pushl $1\n\t" + "pushl $0\n\t" + "pushl $0\n\t" + "pushl %1\n\t" + "pushl %2\n\t" + "pushl %3\n\t" + "pushl %4\n\t" + "pushl %5\n\t" + "pushl %6\n\t" + "pushl %7\n\t" + "call *%%ecx\n\t" + "addl %%esp, $0x2C" + :: + "g" (func), + "g" (pmaxs), + "g" (pmins), + "g" (playermodelindex), + "g" (entity), + "g" (baseline), + "g" (eindex), + "g" (player) + : + "ecx" + ); +#endif } /* ../engine/sv_main.c:6866 */ diff --git a/rehlds/engine/sys_dll.cpp b/rehlds/engine/sys_dll.cpp index 10c5709..5ce8579 100644 --- a/rehlds/engine/sys_dll.cpp +++ b/rehlds/engine/sys_dll.cpp @@ -218,15 +218,25 @@ void Sys_SetupFPUOptions() { static uint8 fpuOpts[32]; +#if defined _MSC_VER || defined __INTEL_COMPILER __asm { fnstenv byte ptr fpuOpts } fpuOpts[0] |= 0x3Fu; __asm { fldenv byte ptr fpuOpts } +#else + asm volatile ("fnstenv %0" : "=m" (fpuOpts)); + fpuOpts[0] |= 0x3Fu; + asm volatile ("fldenv %0" : "=m" (fpuOpts)); +#endif } NOINLINE void Sys_InitFPUControlWords() { int fpucw = 0; +#if defined _MSC_VER || defined __INTEL_COMPILER __asm { fnstcw fpucw } +#else + asm volatile ("fnstcw %0" : "=m" (fpucw)); +#endif g_FPUCW_Mask_Prec_64Bit = (fpucw & 0xF0FF) | 0x300; g_FPUCW_Mask_Prec_64Bit_2 = (fpucw & 0xF0FF) | 0x300; @@ -283,13 +293,27 @@ void __cdecl Sys_InitHardwareTimer() int g_SavedFPUCW1 = 0; NOINLINE void Sys_FPUCW_Push_Prec64() { uint16 tmp = g_FPUCW_Mask_Prec_64Bit; - __asm { fnstcw g_SavedFPUCW1 } - __asm { fldcw tmp } +#if defined _MSC_VER || defined __INTEL_COMPILER + __asm { + fnstcw g_SavedFPUCW1; + fldcw tmp; + } +#else + asm volatile ("fnstcw %0\n\t" + "fldcw %1" : + "=m" (g_SavedFPUCW1), + "=m" (tmp)); +#endif } NOINLINE void Sys_FPUCW_Pop_Prec64() { uint16 tmp = g_SavedFPUCW1; + +#if defined _MSC_VER || defined __INTEL_COMPILER __asm { fldcw tmp } +#else + asm volatile ("fldcw %0" : "=m" (tmp)); +#endif } #endif // _WIN32 diff --git a/rehlds/public/tier0/fasttimer.h b/rehlds/public/tier0/fasttimer.h index d6ef979..429f643 100644 --- a/rehlds/public/tier0/fasttimer.h +++ b/rehlds/public/tier0/fasttimer.h @@ -246,6 +246,7 @@ inline void CCycleCount::Init(float initTimeMsec) inline void CCycleCount::Sample() { unsigned long* pSample = (unsigned long *)&m_Int64; +#if defined _MSC_VER || defined __INTEL_COMPILER __asm { // force the cpu to synchronize the instruction queue @@ -253,11 +254,23 @@ inline void CCycleCount::Sample() //cpuid //cpuid //cpuid - mov ecx, pSample - rdtsc - mov[ecx], eax - mov[ecx + 4], edx + mov ecx, pSample; + rdtsc; + mov [ecx], eax; + mov [ecx + 4], edx; } +#else + asm volatile ( + "movl %%ecx, %0\n\t" + "rdtsc\n\t" + "mov (%%ecx), %%eax\n\t" + "mov $4(%%ecx), %%edx" + :: + "r" (pSample) + : + "eax", "ecx", "edx" + ); +#endif } diff --git a/rehlds/public/tier0/platform.h b/rehlds/public/tier0/platform.h index dbf6c10..0af5c66 100644 --- a/rehlds/public/tier0/platform.h +++ b/rehlds/public/tier0/platform.h @@ -103,7 +103,11 @@ typedef void * HINSTANCE; #endif // Used to step into the debugger +#if defined _MSC_VER || defined __INTEL_COMPILER #define DebuggerBreak() __asm { int 3 } +#else +#define DebuggerBreak() asm volatile ("int 3") +#endif // C functions for external declarations that call the appropriate C++ methods #ifndef EXPORT @@ -263,21 +267,39 @@ inline T DWordSwapC(T dw) template inline T WordSwapAsm(T w) { +#if defined _MSC_VER || defined __INTEL_COMPILER __asm { - mov ax, w - xchg al, ah + mov ax, w; + xchg al, ah; } +#else + asm volatile ( + "movw %%ax, %0\n\t" + "xchgb %%al, %%ah\n\t" + :: + "m" (w) + ); +#endif } template inline T DWordSwapAsm(T dw) { +#if defined _MSC_VER || defined __INTEL_COMPILER __asm { - mov eax, dw - bswap eax + mov eax, dw; + bswap eax; } +#else + asm volatile ( + "movl %%eax, %0\n\t" + "bswapl %%eax\n\t" + :: + "m" (dw) + ); +#endif } #pragma warning(pop) diff --git a/shared.gradle b/shared.gradle index b251219..ce9bcc4 100644 --- a/shared.gradle +++ b/shared.gradle @@ -5,9 +5,11 @@ import org.gradle.nativeplatform.NativeExecutableBinarySpec import org.gradle.nativeplatform.SharedLibraryBinarySpec import org.gradle.nativeplatform.StaticLibraryBinarySpec import org.gradle.nativeplatform.toolchain.VisualCpp +import org.gradle.nativeplatform.toolchain.Clang apply from: 'shared_msvc.gradle' apply from: 'shared_icc.gradle' +apply from: 'shared_llvm.gradle' rootProject.ext.createToolchainConfig = { NativeBinarySpec bin -> BinaryKind binaryKind @@ -27,6 +29,8 @@ rootProject.ext.createToolchainConfig = { NativeBinarySpec bin -> return rootProject.createMsvcConfig(releaseBuild, binaryKind) } else if (bin.toolChain instanceof Icc) { return rootProject.createIccConfig(releaseBuild, binaryKind) + } else if (bin.toolChain instanceof Clang) { + return rootProject.createClangConfig(releaseBuild, binaryKind) } else { throw new RuntimeException("Unknown native toolchain: ${bin.toolChain.class.name}") }