From c4ad2346e3e44448eab8d9797d9797d3711b3e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 15 Nov 2015 23:54:33 +0100 Subject: [PATCH] Fixes for building optimized binary on Linux Use `-DCMAKE_BUILD_TYPE=X`, where X: - `RELEASE` - `RELWITHDEBINFO` - `MINSIZEREL` Only works for GCC, clang binaries crash for now. --- CMakeLists.txt | 4 +- projects/openrct2.vcxproj | 3 +- src/addresses.c | 208 ++++++++++++++++++++++++++++++++++++++ src/addresses.h | 201 +----------------------------------- src/platform/platform.h | 2 +- 5 files changed, 215 insertions(+), 203 deletions(-) create mode 100644 src/addresses.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3664d6f6a1..3eba8200d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,8 @@ file(GLOB_RECURSE ORCT2_SOURCES "src/*.c" "src/*.cpp" "lib/argparse/*.c" "lib/cu if (UNIX) # force 32bit build for now and set necessary flags to compile code as is - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer") set(CMAKE_SHARED_LINKER_FLAGS "-m32") set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) endif (UNIX) diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 75abfce101..7811e240ca 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -28,6 +28,7 @@ + @@ -508,4 +509,4 @@ xcopy /YS "$(SolutionDir)..\Data" "$(TargetDir)Data" - \ No newline at end of file + diff --git a/src/addresses.c b/src/addresses.c new file mode 100644 index 0000000000..0e9f4d3a89 --- /dev/null +++ b/src/addresses.c @@ -0,0 +1,208 @@ +#include "addresses.h" + +#if defined(__GNUC__) +#define DISABLE_OPT __attribute__((noinline,optimize("O0"))) +#else +#define DISABLE_OPT +#endif // defined(__GNUC__) + +int DISABLE_OPT RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx, int _esi, int _edi, int _ebp) +{ + int result; + #ifdef _MSC_VER + __asm { + push ebp + push address + mov eax, _eax + mov ebx, _ebx + mov ecx, _ecx + mov edx, _edx + mov esi, _esi + mov edi, _edi + mov ebp, _ebp + call [esp] + lahf + pop ebp + pop ebp + /* Load result with flags */ + mov result, eax + } + #else + __asm__ volatile ( "\ + \n\ + push %%ebx \n\ + push %%ebp \n\ + push %[address] \n\ + mov %[eax], %%eax \n\ + mov %[ebx], %%ebx \n\ + mov %[ecx], %%ecx \n\ + mov %[edx], %%edx \n\ + mov %[esi], %%esi \n\ + mov %[edi], %%edi \n\ + mov %[ebp], %%ebp \n\ + call *(%%esp) \n\ + lahf \n\ + add $4, %%esp \n\ + pop %%ebp \n\ + pop %%ebx \n\ + /* Load result with flags */ \n\ + mov %%eax, %[result] \n\ + " : [address] "+m" (address), [eax] "+m" (_eax), [ebx] "+m" (_ebx), [ecx] "+m" (_ecx), [edx] "+m" (_edx), [esi] "+m" (_esi), [edi] "+m" (_edi), [ebp] "+m" (_ebp), [result] "+m" (result) + : + : "eax","ecx","edx","esi","edi","memory" + ); + #endif + // lahf only modifies ah, zero out the rest + return result & 0xFF00; +} + +int DISABLE_OPT RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) +{ + int result; + #ifdef _MSC_VER + __asm { + // Store C's base pointer + push ebp + push ebx + // Store address to call + push address + + // Set all registers to the input values + mov eax, [_eax] + mov eax, [eax] + mov ebx, [_ebx] + mov ebx, [ebx] + mov ecx, [_ecx] + mov ecx, [ecx] + mov edx, [_edx] + mov edx, [edx] + mov esi, [_esi] + mov esi, [esi] + mov edi, [_edi] + mov edi, [edi] + mov ebp, [_ebp] + mov ebp, [ebp] + + // Call function + call [esp] + + // Store output eax + push eax + push ebp + push ebx + mov ebp, [esp + 20] + mov ebx, [esp + 16] + + // Get resulting ecx, edx, esi, edi registers + + mov eax, [_edi] + mov [eax], edi + mov eax, [_esi] + mov [eax], esi + mov eax, [_edx] + mov [eax], edx + mov eax, [_ecx] + mov [eax], ecx + + // Pop ebx reg into ecx + pop ecx + mov eax, [_ebx] + mov[eax], ecx + + // Pop ebp reg into ecx + pop ecx + mov eax, [_ebp] + mov[eax], ecx + + pop eax + // Get resulting eax register + mov ecx, [_eax] + mov [ecx], eax + + // Save flags as return in eax + lahf + // Pop address + pop ebp + + pop ebx + pop ebp + /* Load result with flags */ + mov result, eax + } + #else + __asm__ volatile ( "\ + \n\ + /* Store C's base pointer*/ \n\ + push %%ebp \n\ + push %%ebx \n\ + \n\ + /* Store %[address] to call*/ \n\ + push %[address] \n\ + \n\ + /* Set all registers to the input values*/ \n\ + mov %[_eax], %%eax \n\ + mov (%%eax), %%eax \n\ + mov %[_ebx], %%ebx \n\ + mov (%%ebx), %%ebx \n\ + mov %[_ecx], %%ecx \n\ + mov (%%ecx), %%ecx \n\ + mov %[_edx], %%edx \n\ + mov (%%edx), %%edx \n\ + mov %[_esi], %%esi \n\ + mov (%%esi), %%esi \n\ + mov %[_edi], %%edi \n\ + mov (%%edi), %%edi \n\ + mov %[_ebp], %%ebp \n\ + mov (%%ebp), %%ebp \n\ + \n\ + /* Call function*/ \n\ + call *(%%esp) \n\ + \n\ + /* Store output eax */ \n\ + push %%eax \n\ + push %%ebp \n\ + push %%ebx \n\ + mov 20(%%esp), %%ebp \n\ + mov 16(%%esp), %%ebx \n\ + /* Get resulting ecx, edx, esi, edi registers*/ \n\ + mov %[_edi], %%eax \n\ + mov %%edi, (%%eax) \n\ + mov %[_esi], %%eax \n\ + mov %%esi, (%%eax) \n\ + mov %[_edx], %%eax \n\ + mov %%edx, (%%eax) \n\ + mov %[_ecx], %%eax \n\ + mov %%ecx, (%%eax) \n\ + /* Pop ebx reg into ecx*/ \n\ + pop %%ecx \n\ + mov %[_ebx], %%eax \n\ + mov %%ecx, (%%eax) \n\ + \n\ + /* Pop ebp reg into ecx */\n\ + pop %%ecx \n\ + mov %[_ebp], %%eax \n\ + mov %%ecx, (%%eax) \n\ + \n\ + pop %%eax \n\ + /* Get resulting eax register*/ \n\ + mov %[_eax], %%ecx \n\ + mov %%eax, (%%ecx) \n\ + \n\ + /* Save flags as return in eax*/ \n\ + lahf \n\ + /* Pop address*/ \n\ + pop %%ebp \n\ + \n\ + pop %%ebx \n\ + pop %%ebp \n\ + /* Load result with flags */ \n\ + mov %%eax, %[result] \n\ + " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp), [result] "+m" (result) + + : + : "eax","ecx","edx","esi","edi","memory" + ); + #endif + // lahf only modifies ah, zero out the rest + return result & 0xFF00; +} diff --git a/src/addresses.h b/src/addresses.h index e4b4371a39..7f2622284e 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -650,55 +650,7 @@ *P = Parity flag *All other bits are undefined. */ -static int RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx, int _esi, int _edi, int _ebp) -{ - int result; - #ifdef _MSC_VER - __asm { - push ebp - push address - mov eax, _eax - mov ebx, _ebx - mov ecx, _ecx - mov edx, _edx - mov esi, _esi - mov edi, _edi - mov ebp, _ebp - call [esp] - lahf - pop ebp - pop ebp - /* Load result with flags */ - mov result, eax - } - #else - __asm__ ( "\ - \n\ - push %%ebx \n\ - push %%ebp \n\ - push %[address] \n\ - mov %[_eax], %%eax \n\ - mov %[_ebx], %%ebx \n\ - mov %[_ecx], %%ecx \n\ - mov %[_edx], %%edx \n\ - mov %[_esi], %%esi \n\ - mov %[_edi], %%edi \n\ - mov %[_ebp], %%ebp \n\ - call *(%%esp) \n\ - lahf \n\ - add $4, %%esp \n\ - pop %%ebp \n\ - pop %%ebx \n\ - /* Load result with flags */ \n\ - mov %%eax, %[result] \n\ - " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp), [result] "+m" (result) - : - : "eax","ecx","edx","esi","edi" - ); - #endif - // lahf only modifies ah, zero out the rest - return result & 0xFF00; -} +int RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx, int _esi, int _edi, int _ebp); static int RCT2_CALLPROC_EBPSAFE(int address) { @@ -716,156 +668,7 @@ static int RCT2_CALLPROC_EBPSAFE(int address) *P = Parity flag *All other bits are undefined. */ -static int RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp) -{ - int result; - #ifdef _MSC_VER - __asm { - // Store C's base pointer - push ebp - push ebx - // Store address to call - push address - - // Set all registers to the input values - mov eax, [_eax] - mov eax, [eax] - mov ebx, [_ebx] - mov ebx, [ebx] - mov ecx, [_ecx] - mov ecx, [ecx] - mov edx, [_edx] - mov edx, [edx] - mov esi, [_esi] - mov esi, [esi] - mov edi, [_edi] - mov edi, [edi] - mov ebp, [_ebp] - mov ebp, [ebp] - - // Call function - call [esp] - - // Store output eax - push eax - push ebp - push ebx - mov ebp, [esp + 20] - mov ebx, [esp + 16] - - // Get resulting ecx, edx, esi, edi registers - - mov eax, [_edi] - mov [eax], edi - mov eax, [_esi] - mov [eax], esi - mov eax, [_edx] - mov [eax], edx - mov eax, [_ecx] - mov [eax], ecx - - // Pop ebx reg into ecx - pop ecx - mov eax, [_ebx] - mov[eax], ecx - - // Pop ebp reg into ecx - pop ecx - mov eax, [_ebp] - mov[eax], ecx - - pop eax - // Get resulting eax register - mov ecx, [_eax] - mov [ecx], eax - - // Save flags as return in eax - lahf - // Pop address - pop ebp - - pop ebx - pop ebp - /* Load result with flags */ - mov result, eax - } - #else - __asm__ ( "\ - \n\ - /* Store C's base pointer*/ \n\ - push %%ebp \n\ - push %%ebx \n\ - \n\ - /* Store %[address] to call*/ \n\ - push %[address] \n\ - \n\ - /* Set all registers to the input values*/ \n\ - mov %[_eax], %%eax \n\ - mov (%%eax), %%eax \n\ - mov %[_ebx], %%ebx \n\ - mov (%%ebx), %%ebx \n\ - mov %[_ecx], %%ecx \n\ - mov (%%ecx), %%ecx \n\ - mov %[_edx], %%edx \n\ - mov (%%edx), %%edx \n\ - mov %[_esi], %%esi \n\ - mov (%%esi), %%esi \n\ - mov %[_edi], %%edi \n\ - mov (%%edi), %%edi \n\ - mov %[_ebp], %%ebp \n\ - mov (%%ebp), %%ebp \n\ - \n\ - /* Call function*/ \n\ - call *(%%esp) \n\ - \n\ - /* Store output eax */ \n\ - push %%eax \n\ - push %%ebp \n\ - push %%ebx \n\ - mov 20(%%esp), %%ebp \n\ - mov 16(%%esp), %%ebx \n\ - /* Get resulting ecx, edx, esi, edi registers*/ \n\ - mov %[_edi], %%eax \n\ - mov %%edi, (%%eax) \n\ - mov %[_esi], %%eax \n\ - mov %%esi, (%%eax) \n\ - mov %[_edx], %%eax \n\ - mov %%edx, (%%eax) \n\ - mov %[_ecx], %%eax \n\ - mov %%ecx, (%%eax) \n\ - /* Pop ebx reg into ecx*/ \n\ - pop %%ecx \n\ - mov %[_ebx], %%eax \n\ - mov %%ecx, (%%eax) \n\ - \n\ - /* Pop ebp reg into ecx */\n\ - pop %%ecx \n\ - mov %[_ebp], %%eax \n\ - mov %%ecx, (%%eax) \n\ - \n\ - pop %%eax \n\ - /* Get resulting eax register*/ \n\ - mov %[_eax], %%ecx \n\ - mov %%eax, (%%ecx) \n\ - \n\ - /* Save flags as return in eax*/ \n\ - lahf \n\ - /* Pop address*/ \n\ - pop %%ebp \n\ - \n\ - pop %%ebx \n\ - pop %%ebp \n\ - /* Load result with flags */ \n\ - mov %%eax, %[result] \n\ - " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp), [result] "+m" (result) - - : - : "eax","ecx","edx","esi","edi" - ); - #endif - // lahf only modifies ah, zero out the rest - return result & 0xFF00; -} +int RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp); typedef struct { union { diff --git a/src/platform/platform.h b/src/platform/platform.h index a8c4b260d8..0cf3c727ee 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -183,7 +183,7 @@ bool platform_check_steam_overlay_attached(); #endif // __linux__ -#if !(POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) +#if !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) char *strndup(const char *src, size_t size); #endif // !(POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)