From fe79b0dc2942c5ed66387f04dd08417cdc7d3919 Mon Sep 17 00:00:00 2001 From: Sterling Alexander Date: Wed, 8 Jan 2020 19:33:14 -0500 Subject: [PATCH] Adjust the source code and build enviornment so that Mangos Zero will build on ARM32. (#79) This was primarily done to test the feasibility of running on a RPi4 running Debian Buster (it works quite well). Summary of changes: - Reworked patches I found on the Mangos forum, original pastebins here: https://pastebin.com/BxqCmCML - Adjusted cmake's arch detection to include ARM32/ARM64 - Adjusted compiler flags for Linux builds and supressed some extraneous notes I have played for about an hour and noticed no issues or differences from i386/x86_64 VMs. One note, currently the map extraction tools for ARM are broken. They compile but do work properly. I'll work on that next. --- cmake/SetDefinitions.cmake | 23 ++++++++++++++++++++--- src/shared/Database/SQLStorageImpl.h | 24 ++++++++++++++++++++++++ src/shared/Utilities/ByteBuffer.h | 6 ++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/cmake/SetDefinitions.cmake b/cmake/SetDefinitions.cmake index f1211d30..b7bc132f 100644 --- a/cmake/SetDefinitions.cmake +++ b/cmake/SetDefinitions.cmake @@ -23,14 +23,21 @@ else() endif() if(XCODE) - if(PLATFORM MATCHES 32) + # Here we add a check for ARM32, as they can't leverage SSE/SSE2 + if(PLATFORM MATCHES 32 AND ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm") + set(CMAKE_OSX_ARCHITECTURES ARM32) + # Default for 32-bit left as i386 + elseif(PLATFORM MATCHES 32) set(CMAKE_OSX_ARCHITECTURES i386) + # Check for ARM64 + elseif(PLATFORM MATCHES 64 AND ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm") + set(CMAKE_OSX_ARCHITECTURES ARM64) + # Default for 64-bit left as x86_64 else() set(CMAKE_OSX_ARCHITECTURES x86_64) endif() endif() - # # Compile definitions # @@ -112,10 +119,17 @@ endif () # GCC compiler options if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") set(DEFAULT_COMPILE_OPTS ${DEFAULT_COMPILE_OPTS} - $<$: + # Enhanced 32-bit check, now we can use the arch to specify flags + $<$: -msse2 -mfpmath=sse > + $<$: + # explicit space for compiler flags + > + $<$: + # explicit space for compiler flags + > $<$: -W -Wall @@ -128,6 +142,9 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") $<$: --no-warnings + # Suppress compiler note on parameter passing. See the following + # GCC BZ for more info: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728 + -Wno-psabi > ) endif () diff --git a/src/shared/Database/SQLStorageImpl.h b/src/shared/Database/SQLStorageImpl.h index 1a50ec31..cf1db648 100644 --- a/src/shared/Database/SQLStorageImpl.h +++ b/src/shared/Database/SQLStorageImpl.h @@ -40,6 +40,14 @@ template */ void SQLStorageLoaderBase::convert(uint32 /*field_pos*/, S src, D& dst) { +#if defined(__arm__) + if (((unsigned) &dst) % sizeof(D)) { + //The address is not aligned. Use memcpy to avoid ARM unaligned trap + D converted(src); + memcpy((void*) &dst, (void*) &converted, sizeof(D)); + } + else +#endif dst = D(src); } @@ -92,6 +100,14 @@ template */ void SQLStorageLoaderBase::convert_from_str(uint32 /*field_pos*/, char const* /*src*/, D& dst) { +#if defined(__arm__) + if (((unsigned) &dst) % sizeof(D)) { + //The address is not aligned. Use memcpy to avoid ARM unaligned trap + D converted(0); + memcpy((void*) &dst, (void*) &converted, sizeof(D)); + } + else +#endif dst = 0; } @@ -106,6 +122,14 @@ template */ void SQLStorageLoaderBase::default_fill(uint32 /*field_pos*/, S src, D& dst) { +#if defined(__arm__) + if (((unsigned) &dst) % sizeof(D)) { + //The address is not aligned. Use memcpy to avoid ARM unaligned trap + D converted(src); + memcpy((void*) &dst, (void*) &converted, sizeof(D)); + } + else +#endif dst = D(src); } diff --git a/src/shared/Utilities/ByteBuffer.h b/src/shared/Utilities/ByteBuffer.h index 32ad9069..cf17f6de 100644 --- a/src/shared/Utilities/ByteBuffer.h +++ b/src/shared/Utilities/ByteBuffer.h @@ -534,7 +534,13 @@ class ByteBuffer { if (pos + sizeof(T) > size()) { throw ByteBufferException(false, pos, sizeof(T), size()); } +#if defined(__arm__) + // ARM has alignment issues, we need to use memcpy to avoid them + T val; + memcpy((void*)&val, (void*)&_storage[pos], sizeof(T)); +#else T val = *((T const*)&_storage[pos]); +#endif EndianConvert(val); return val; }