From aa4f8b6fa78eb8331b5927ba5315b926ac75ce9c Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 26 Nov 2017 22:23:23 +0300 Subject: [PATCH] #216 Added ARMv7 support. --- CMakeLists.txt | 6 +-- cmake/cpu.cmake | 11 +++++- cmake/flags.cmake | 10 ++++- src/Cpu_arm.cpp | 2 + src/crypto/CryptoNight.cpp | 12 +++++- ...{CryptoNight_arm64.h => CryptoNight_arm.h} | 39 +++++++++++++++++-- src/crypto/CryptoNight_x86.h | 6 +-- src/crypto/soft_aes.h | 2 +- src/log/ConsoleLog.cpp | 2 +- 9 files changed, 74 insertions(+), 16 deletions(-) rename src/crypto/{CryptoNight_arm64.h => CryptoNight_arm.h} (93%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 64d504f7..0a1f238a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,8 +64,8 @@ set(HEADERS_CRYPTO src/crypto/soft_aes.h ) -if (XMRIG_ARM64) - set(HEADERS_CRYPTO "${HEADERS_CRYPTO}" src/crypto/CryptoNight_arm64.h) +if (XMRIG_ARM) + set(HEADERS_CRYPTO "${HEADERS_CRYPTO}" src/crypto/CryptoNight_arm.h) else() set(HEADERS_CRYPTO "${HEADERS_CRYPTO}" src/crypto/CryptoNight_x86.h) endif() @@ -168,7 +168,7 @@ if (WITH_LIBCPUID) else() add_definitions(/DXMRIG_NO_LIBCPUID) - if (XMRIG_ARM64) + if (XMRIG_ARM) set(SOURCES_CPUID src/Cpu_arm.cpp) else() set(SOURCES_CPUID src/Cpu_stub.cpp) diff --git a/cmake/cpu.cmake b/cmake/cpu.cmake index 56bbef96..96e61e2b 100644 --- a/cmake/cpu.cmake +++ b/cmake/cpu.cmake @@ -9,8 +9,17 @@ endif() if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64)$") - set(XMRIG_ARM64 ON) + set(XMRIG_ARM ON) + set(XMRIG_ARMv8 ON) set(WITH_LIBCPUID OFF) add_definitions(/DXMRIG_ARM) + add_definitions(/DXMRIG_ARMv8) +elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7|armv7f|armv7s|armv7k|armv7-a|armv7l)$") + set(XMRIG_ARM ON) + set(XMRIG_ARMv7 ON) + set(WITH_LIBCPUID OFF) + + add_definitions(/DXMRIG_ARM) + add_definitions(/DXMRIG_ARMv7) endif() diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 7f32e115..488f1236 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -14,9 +14,12 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-exceptions -fno-rtti") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2") - if (CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) + if (XMRIG_ARMv8) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a+crypto") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a+crypto -flax-vector-conversions") + elseif (XMRIG_ARMv7) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -flax-vector-conversions") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") @@ -52,9 +55,12 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-exceptions -fno-rtti -Wno-missing-braces") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants") - if (CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) + if (XMRIG_ARMv8) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a+crypto") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a+crypto") + elseif (XMRIG_ARMv7) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") diff --git a/src/Cpu_arm.cpp b/src/Cpu_arm.cpp index 906e0156..c2047ffb 100644 --- a/src/Cpu_arm.cpp +++ b/src/Cpu_arm.cpp @@ -47,6 +47,8 @@ void Cpu::initCommon() { memcpy(m_brand, "Unknown", 7); +# if defined(XMRIG_ARMv8) m_flags |= X86_64; m_flags |= AES; +# endif } diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp index 6fdf9d92..3ac9e94b 100644 --- a/src/crypto/CryptoNight.cpp +++ b/src/crypto/CryptoNight.cpp @@ -24,8 +24,8 @@ #include "crypto/CryptoNight.h" -#if defined(__aarch64__) -# include "crypto/CryptoNight_arm64.h" +#if defined(XMRIG_ARM) +# include "crypto/CryptoNight_arm.h" #else # include "crypto/CryptoNight_x86.h" #endif @@ -40,12 +40,16 @@ void (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, crypt static void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) { +# if !defined(XMRIG_ARMv7) cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); +# endif } static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { +# if !defined(XMRIG_ARMv7) cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); +# endif } @@ -61,12 +65,16 @@ static void cryptonight_av4_softaes_double(const void *input, size_t size, void #ifndef XMRIG_NO_AEON static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { + # if !defined(XMRIG_ARMv7) cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); +#endif } static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { +# if !defined(XMRIG_ARMv7) cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); +# endif } diff --git a/src/crypto/CryptoNight_arm64.h b/src/crypto/CryptoNight_arm.h similarity index 93% rename from src/crypto/CryptoNight_arm64.h rename to src/crypto/CryptoNight_arm.h index 4d70b20d..15be6c3d 100644 --- a/src/crypto/CryptoNight_arm64.h +++ b/src/crypto/CryptoNight_arm.h @@ -22,8 +22,8 @@ * along with this program. If not, see . */ -#ifndef __CRYPTONIGHT_ARM64_H__ -#define __CRYPTONIGHT_ARM64_H__ +#ifndef __CRYPTONIGHT_ARM_H__ +#define __CRYPTONIGHT_ARM_H__ #if defined(XMRIG_ARM) && !defined(__clang__) @@ -86,12 +86,39 @@ static inline __attribute__((always_inline)) uint64_t _mm_cvtsi128_si64(__m128i #define EXTRACT64(X) _mm_cvtsi128_si64(X) +#if defined(XMRIG_ARMv8) static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi) { unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b; *hi = r >> 64; return (uint64_t) r; } +#else +static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) { + // multiplier = ab = a * 2^32 + b + // multiplicand = cd = c * 2^32 + d + // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d + uint64_t a = multiplier >> 32; + uint64_t b = multiplier & 0xFFFFFFFF; + uint64_t c = multiplicand >> 32; + uint64_t d = multiplicand & 0xFFFFFFFF; + + //uint64_t ac = a * c; + uint64_t ad = a * d; + //uint64_t bc = b * c; + uint64_t bd = b * d; + + uint64_t adbc = ad + (b * c); + uint64_t adbc_carry = adbc < ad ? 1 : 0; + + // multiplier * multiplicand = product_hi * 2^64 + product_lo + uint64_t product_lo = bd + (adbc << 32); + uint64_t product_lo_carry = product_lo < bd ? 1 : 0; + *product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry; + + return product_lo; +} +#endif // This will shift and xor tmp1 into itself as 4 32-bit vals such as @@ -176,6 +203,7 @@ static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, *x6 = soft_aesenc(*x6, key); *x7 = soft_aesenc(*x7, key); } +# ifndef XMRIG_ARMv7 else { *x0 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x0), key)); *x1 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x1), key)); @@ -186,6 +214,7 @@ static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, *x6 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x6), key)); *x7 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x7), key)); } +# endif } @@ -338,7 +367,9 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0)); } else { +# ifndef XMRIG_ARMv7 cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); +# endif } _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); @@ -402,8 +433,10 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1)); } else { +# ifndef XMRIG_ARMv7 cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1); +# endif } _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); @@ -455,4 +488,4 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast(output) + 32); } -#endif /* __CRYPTONIGHT_ARM64_H__ */ +#endif /* __CRYPTONIGHT_ARM_H__ */ diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 75809b81..362a1a9f 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -21,8 +21,8 @@ * along with this program. If not, see . */ -#ifndef __CRYPTONIGHT_P_H__ -#define __CRYPTONIGHT_P_H__ +#ifndef __CRYPTONIGHT_X86_H__ +#define __CRYPTONIGHT_X86_H__ #ifdef __GNUC__ @@ -448,4 +448,4 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast(output) + 32); } -#endif /* __CRYPTONIGHT_P_H__ */ +#endif /* __CRYPTONIGHT_X86_H__ */ diff --git a/src/crypto/soft_aes.h b/src/crypto/soft_aes.h index 4b1d346f..99321c4e 100644 --- a/src/crypto/soft_aes.h +++ b/src/crypto/soft_aes.h @@ -27,7 +27,7 @@ #pragma once -#if defined(__aarch64__) +#if defined(XMRIG_ARM) # include "crypto/SSE2NEON.h" #elif defined(__GNUC__) # include diff --git a/src/log/ConsoleLog.cpp b/src/log/ConsoleLog.cpp index 45733858..3656d48c 100644 --- a/src/log/ConsoleLog.cpp +++ b/src/log/ConsoleLog.cpp @@ -145,7 +145,7 @@ void ConsoleLog::print(va_list args) } if (!isWritable()) { - fprintf(stdout, m_buf); + fputs(m_buf, stdout); fflush(stdout); } else {