Parallel hashes

This commit is contained in:
Andrea Mazzoleni 2026-07-13 00:44:18 +02:00
parent 13844afe4c
commit e63e79d51a
11 changed files with 1953 additions and 1 deletions

View file

@ -109,10 +109,14 @@ noinst_HEADERS = \
cmdline/murmur3test.c \
cmdline/spooky2.c \
cmdline/spooky2test.c \
cmdline/spooky2sse.c \
cmdline/spooky2avx.c \
cmdline/metro.c \
cmdline/metrotest.c \
cmdline/museair.c \
cmdline/museairtest.c \
cmdline/museairsse.c \
cmdline/museairavx.c \
cmdline/import.h \
cmdline/search.h \
cmdline/thermal.h \

View file

@ -5,3 +5,4 @@
#define HAVE_CHECKER 1
#include "snapraid.c"

View file

@ -56,7 +56,7 @@ static const uint64_t MASK_I = 01555555555555555555555ULL;
static const uint64_t MASK_J = 01333333333333333333333ULL;
static const uint64_t MASK_K = 00666666666666666666666ULL;
static void MuseAirLoong(const void* bytes, size_t len, const uint8_t* seed, uint8_t* out)
void MuseAirLoong(const void* bytes, size_t len, const uint8_t* seed, uint8_t* out)
{
const uint8_t* p = bytes;
size_t q = len;

476
cmdline/museairavx.c Normal file
View file

@ -0,0 +1,476 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2026 Andrea Mazzoleni
#if defined(__x86_64__)
#define AVX_LOAD(offset, dest) \
"vmovq " #offset "*8(%[blocks0]), %%xmm14\n\t" \
"vmovhps " #offset "*8(%[blocks1]), %%xmm14, %%xmm14\n\t" \
"vmovq " #offset "*8(%[blocks2]), %%xmm15\n\t" \
"vmovhps " #offset "*8(%[blocks3]), %%xmm15, %%xmm15\n\t" \
"vinserti128 $1, %%xmm15, %%ymm14, " dest "\n\t"
#define AVX_LOAD_NEG(offset, dest) \
"vmovq -" #offset "(%%r8), %%xmm14\n\t" \
"vmovhps -" #offset "(%%r9), %%xmm14, %%xmm14\n\t" \
"vmovq -" #offset "(%%r10), %%xmm15\n\t" \
"vmovhps -" #offset "(%%r11), %%xmm15, %%xmm15\n\t" \
"vinserti128 $1, %%xmm15, %%ymm14, " dest "\n\t"
#define AVX_MULT(ymm_a, ymm_b, ymm_lo, ymm_hi) \
/* 1. ymm_ll = ymm_a * ymm_b (low parts) */ \
"vpmuludq " ymm_b ", " ymm_a ", %%ymm8\n\t" /* ymm8 = P_ll */ \
/* 2. ymm_lh = ymm_a * ymm_b_high */ \
"vpsrlq $32, " ymm_b ", %%ymm9\n\t" /* ymm9 = B_h */ \
"vpmuludq %%ymm9, " ymm_a ", %%ymm10\n\t" /* ymm10 = P_lh */ \
/* 3. ymm_hl = ymm_a_high * ymm_b */ \
"vpsrlq $32, " ymm_a ", %%ymm14\n\t" /* ymm14 = A_h */ \
"vpmuludq " ymm_b ", %%ymm14, %%ymm15\n\t" /* ymm15 = P_hl */ \
/* 4. ymm_hh = ymm_a_high * ymm_b_high */ \
"vpmuludq %%ymm9, %%ymm14, %%ymm9\n\t" /* ymm9 = P_hh */ \
/* 5. M = P_lh + P_hl */ \
"vpaddq %%ymm15, %%ymm10, %%ymm15\n\t" /* ymm15 = M */ \
/* Generate mask 0xffffffff in ymm14 */ \
"vpcmpeqd %%ymm14, %%ymm14, %%ymm14\n\t" \
"vpsrlq $32, %%ymm14, %%ymm14\n\t" \
/* 6. Split M into ymm10 = M_low, ymm15 = M_high */ \
"vpand %%ymm14, %%ymm15, %%ymm10\n\t" /* ymm10 = M_low */ \
"vpsrlq $32, %%ymm15, %%ymm15\n\t" /* ymm15 = M_high */ \
/* 7. Split P_ll (in ymm8) into ymm12 = P_lll, ymm13 = P_llh */ \
"vpsrlq $32, %%ymm8, %%ymm13\n\t" /* ymm13 = P_llh */ \
"vpand %%ymm14, %%ymm8, %%ymm12\n\t" /* ymm12 = P_lll */ \
/* 8. S1 = P_llh + M_low */ \
"vpaddq %%ymm10, %%ymm13, %%ymm10\n\t" /* ymm10 = S1 */ \
/* 9. Split S1 into ymm13 = C1, ymm10 = S1_l */ \
"vpsrlq $32, %%ymm10, %%ymm13\n\t" /* ymm13 = C1 */ \
"vpand %%ymm14, %%ymm10, %%ymm10\n\t" /* ymm10 = S1_l */ \
/* 10. Assemble final low = P_lll + S1_l * 2^32 */ \
"vpsllq $32, %%ymm10, %%ymm10\n\t" \
"vpaddq %%ymm12, %%ymm10, " ymm_lo "\n\t" /* ymm_lo = final low */ \
/* 11. Split P_hh (in ymm9) into ymm12 = P_hhl, ymm10 = P_hhh */ \
"vpsrlq $32, %%ymm9, %%ymm10\n\t" /* ymm10 = P_hhh */ \
"vpand %%ymm14, %%ymm9, %%ymm12\n\t" /* ymm12 = P_hhl */ \
/* 12. Assemble final high = M_high + P_hhl + C1 + P_hhh * 2^32 */ \
"vpaddq %%ymm12, %%ymm15, %%ymm15\n\t" /* ymm15 = M_high + P_hhl */ \
"vpaddq %%ymm13, %%ymm15, %%ymm15\n\t" /* ymm15 = M_high + P_hhl + C1 */ \
"vpsllq $32, %%ymm10, %%ymm10\n\t" \
"vpaddq %%ymm10, %%ymm15, " ymm_hi "\n\t" /* ymm_hi = final high */
void MuseAirLoongAVX(
const void* data0, const void* data1, const void* data2, const void* data3,
size_t size,
const uint8_t* seed0, const uint8_t* seed1, const uint8_t* seed2, const uint8_t* seed3,
uint8_t* digest0, uint8_t* digest1, uint8_t* digest2, uint8_t* digest3
)
{
uint64_t buf0[12];
uint64_t buf1[12];
uint64_t buf2[12];
uint64_t buf3[12];
const uint8_t* blocks0 = data0;
const uint8_t* blocks1 = data1;
const uint8_t* blocks2 = data2;
const uint8_t* blocks3 = data3;
size_t q = size;
if (q < 32) {
memset(buf0, 0, 32);
memset(buf1, 0, 32);
memset(buf2, 0, 32);
memset(buf3, 0, 32);
if (q > 0) {
memcpy(buf0, blocks0, q);
memcpy(buf1, blocks1, q);
memcpy(buf2, blocks2, q);
memcpy(buf3, blocks3, q);
}
blocks0 = (const uint8_t*)buf0;
blocks1 = (const uint8_t*)buf1;
blocks2 = (const uint8_t*)buf2;
blocks3 = (const uint8_t*)buf3;
q = 32;
}
uint64_t rot = size & 63;
uint64_t rot_diff = 64 - rot;
static const uint64_t const_mask_i = 01555555555555555555555ULL;
static const uint64_t const_mask_j = 01333333333333333333333ULL;
static const uint64_t const_mask_k = 00666666666666666666666ULL;
__asm__ __volatile__ (
/* Load seeds */
"movq %[seed0], %%rax\n\t"
"vmovq (%%rax), %%xmm9\n\t"
"movq %[seed1], %%rax\n\t"
"vmovhps (%%rax), %%xmm9, %%xmm9\n\t"
"movq %[seed2], %%rax\n\t"
"vmovq (%%rax), %%xmm13\n\t"
"movq %[seed3], %%rax\n\t"
"vmovhps (%%rax), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm9, %%ymm9\n\t" /* ymm9 = seed_a */
"movq %[seed0], %%rax\n\t"
"vmovq 8(%%rax), %%xmm10\n\t"
"movq %[seed1], %%rax\n\t"
"vmovhps 8(%%rax), %%xmm10, %%xmm10\n\t"
"movq %[seed2], %%rax\n\t"
"vmovq 8(%%rax), %%xmm13\n\t"
"movq %[seed3], %%rax\n\t"
"vmovhps 8(%%rax), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm10, %%ymm10\n\t" /* ymm10 = seed_b */
/* Load masks */
"vmovq %[mask_i], %%xmm12\n\t"
"vpunpcklqdq %%xmm12, %%xmm12, %%xmm12\n\t"
"vinserti128 $1, %%xmm12, %%ymm12, %%ymm12\n\t"
"vmovq %[mask_j], %%xmm13\n\t"
"vpunpcklqdq %%xmm13, %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm13, %%ymm13\n\t"
"vmovq %[mask_k], %%xmm14\n\t"
"vpunpcklqdq %%xmm14, %%xmm14, %%xmm14\n\t"
"vinserti128 $1, %%xmm14, %%ymm14, %%ymm14\n\t"
/* Initialize states */
"leaq %[const_ptr], %%rax\n\t"
/* state0 */
"vmovq 0*8(%%rax), %%xmm0\n\t"
"vpunpcklqdq %%xmm0, %%xmm0, %%xmm0\n\t"
"vinserti128 $1, %%xmm0, %%ymm0, %%ymm0\n\t"
"vpand %%ymm12, %%ymm9, %%ymm15\n\t"
"vpxor %%ymm15, %%ymm0, %%ymm0\n\t"
/* state1 */
"vmovq 1*8(%%rax), %%xmm1\n\t"
"vpunpcklqdq %%xmm1, %%xmm1, %%xmm1\n\t"
"vinserti128 $1, %%xmm1, %%ymm1, %%ymm1\n\t"
"vpand %%ymm13, %%ymm10, %%ymm15\n\t"
"vpxor %%ymm15, %%ymm1, %%ymm1\n\t"
/* state2 */
"vmovq 2*8(%%rax), %%xmm2\n\t"
"vpunpcklqdq %%xmm2, %%xmm2, %%xmm2\n\t"
"vinserti128 $1, %%xmm2, %%ymm2, %%ymm2\n\t"
"vpand %%ymm14, %%ymm9, %%ymm15\n\t"
"vpxor %%ymm15, %%ymm2, %%ymm2\n\t"
/* state3 */
"vmovq 3*8(%%rax), %%xmm3\n\t"
"vpunpcklqdq %%xmm3, %%xmm3, %%xmm3\n\t"
"vinserti128 $1, %%xmm3, %%ymm3, %%ymm3\n\t"
"vpand %%ymm12, %%ymm10, %%ymm15\n\t"
"vpxor %%ymm15, %%ymm3, %%ymm3\n\t"
/* state4 */
"vmovq 4*8(%%rax), %%xmm4\n\t"
"vpunpcklqdq %%xmm4, %%xmm4, %%xmm4\n\t"
"vinserti128 $1, %%xmm4, %%ymm4, %%ymm4\n\t"
"vpand %%ymm13, %%ymm9, %%ymm15\n\t"
"vpxor %%ymm15, %%ymm4, %%ymm4\n\t"
/* state5 */
"vmovq 5*8(%%rax), %%xmm5\n\t"
"vpunpcklqdq %%xmm5, %%xmm5, %%xmm5\n\t"
"vinserti128 $1, %%xmm5, %%ymm5, %%ymm5\n\t"
"vpand %%ymm14, %%ymm10, %%ymm15\n\t"
"vpxor %%ymm15, %%ymm5, %%ymm5\n\t"
/* lo5 and hi5 */
"vmovq 6*8(%%rax), %%xmm6\n\t"
"vpunpcklqdq %%xmm6, %%xmm6, %%xmm6\n\t"
"vinserti128 $1, %%xmm6, %%ymm6, %%ymm6\n\t"
"vmovdqa %%ymm6, %%ymm7\n\t"
/* Conditional loop */
"cmp $96, %[q]\n\t"
"jbe 3f\n\t"
"1:\n\t"
/* Loop step idx = 0 */
AVX_LOAD(0, "%%ymm15")
"vpxor %%ymm15, %%ymm0, %%ymm0\n\t"
AVX_LOAD(1, "%%ymm15")
"vpxor %%ymm15, %%ymm1, %%ymm1\n\t"
AVX_MULT("%%ymm0", "%%ymm1", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm6, %%ymm0\n\t"
"vmovdqa %%ymm8, %%ymm10\n\t"
/* Loop step idx = 1 */
AVX_LOAD(2, "%%ymm15")
"vpxor %%ymm15, %%ymm1, %%ymm1\n\t"
AVX_LOAD(3, "%%ymm15")
"vpxor %%ymm15, %%ymm2, %%ymm2\n\t"
AVX_MULT("%%ymm1", "%%ymm2", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm10, %%ymm1\n\t"
"vmovdqa %%ymm8, %%ymm10\n\t"
/* Loop step idx = 2 */
AVX_LOAD(4, "%%ymm15")
"vpxor %%ymm15, %%ymm2, %%ymm2\n\t"
AVX_LOAD(5, "%%ymm15")
"vpxor %%ymm15, %%ymm3, %%ymm3\n\t"
AVX_MULT("%%ymm2", "%%ymm3", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm10, %%ymm2\n\t"
"vmovdqa %%ymm8, %%ymm10\n\t"
/* Loop step idx = 3 */
AVX_LOAD(6, "%%ymm15")
"vpxor %%ymm15, %%ymm3, %%ymm3\n\t"
AVX_LOAD(7, "%%ymm15")
"vpxor %%ymm15, %%ymm4, %%ymm4\n\t"
AVX_MULT("%%ymm3", "%%ymm4", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm10, %%ymm3\n\t"
"vmovdqa %%ymm8, %%ymm10\n\t"
/* Loop step idx = 4 */
AVX_LOAD(8, "%%ymm15")
"vpxor %%ymm15, %%ymm4, %%ymm4\n\t"
AVX_LOAD(9, "%%ymm15")
"vpxor %%ymm15, %%ymm5, %%ymm5\n\t"
AVX_MULT("%%ymm4", "%%ymm5", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm10, %%ymm4\n\t"
"vmovdqa %%ymm8, %%ymm10\n\t"
/* Loop step idx = 5 */
AVX_LOAD(10, "%%ymm15")
"vpxor %%ymm15, %%ymm5, %%ymm5\n\t"
AVX_LOAD(11, "%%ymm15")
"vpxor %%ymm15, %%ymm0, %%ymm0\n\t"
AVX_MULT("%%ymm5", "%%ymm0", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm10, %%ymm5\n\t"
"vmovdqa %%ymm8, %%ymm6\n\t"
"vmovdqa %%ymm9, %%ymm7\n\t"
"add $96, %[blocks0]\n\t"
"add $96, %[blocks1]\n\t"
"add $96, %[blocks2]\n\t"
"add $96, %[blocks3]\n\t"
"sub $96, %[q]\n\t"
"cmp $96, %[q]\n\t"
"ja 1b\n\t"
"vpxor %%ymm6, %%ymm0, %%ymm0\n\t"
"3:\n\t"
/* Tail */
"vmovdqa %%ymm1, %%ymm10\n\t" /* xor0 = state1 */
"vmovdqa %%ymm2, %%ymm11\n\t" /* xor1 = state2 */
"vmovdqa %%ymm3, %%ymm12\n\t" /* xor2 = state3 */
"vmovdqa %%ymm4, %%ymm13\n\t" /* xor3 = state4 */
"cmp $32, %[q]\n\t"
"jbe 4f\n\t"
AVX_LOAD(0, "%%ymm15")
"vpxor %%ymm15, %%ymm0, %%ymm0\n\t"
AVX_LOAD(1, "%%ymm15")
"vpxor %%ymm15, %%ymm1, %%ymm1\n\t"
AVX_MULT("%%ymm0", "%%ymm1", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm8, %%ymm10\n\t"
"cmp $48, %[q]\n\t"
"jbe 4f\n\t"
AVX_LOAD(2, "%%ymm15")
"vpxor %%ymm15, %%ymm1, %%ymm1\n\t"
AVX_LOAD(3, "%%ymm15")
"vpxor %%ymm15, %%ymm2, %%ymm2\n\t"
AVX_MULT("%%ymm1", "%%ymm2", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm8, %%ymm11\n\t"
"cmp $64, %[q]\n\t"
"jbe 4f\n\t"
AVX_LOAD(4, "%%ymm15")
"vpxor %%ymm15, %%ymm2, %%ymm2\n\t"
AVX_LOAD(5, "%%ymm15")
"vpxor %%ymm15, %%ymm3, %%ymm3\n\t"
AVX_MULT("%%ymm2", "%%ymm3", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm8, %%ymm12\n\t"
"cmp $80, %[q]\n\t"
"jbe 4f\n\t"
AVX_LOAD(6, "%%ymm15")
"vpxor %%ymm15, %%ymm3, %%ymm3\n\t"
AVX_LOAD(7, "%%ymm15")
"vpxor %%ymm15, %%ymm4, %%ymm4\n\t"
AVX_MULT("%%ymm3", "%%ymm4", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm8, %%ymm13\n\t"
"4:\n\t"
/* Compute end pointers */
"movq %[blocks0], %%r8\n\t"
"add %[q], %%r8\n\t"
"movq %[blocks1], %%r9\n\t"
"add %[q], %%r9\n\t"
"movq %[blocks2], %%r10\n\t"
"add %[q], %%r10\n\t"
"movq %[blocks3], %%r11\n\t"
"add %[q], %%r11\n\t"
/* Unconditional tail step 1 */
AVX_LOAD_NEG(32, "%%ymm15")
"vpxor %%ymm15, %%ymm4, %%ymm4\n\t"
AVX_LOAD_NEG(24, "%%ymm15")
"vpxor %%ymm15, %%ymm5, %%ymm5\n\t"
AVX_MULT("%%ymm4", "%%ymm5", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm8, %%ymm14\n\t"
/* Unconditional tail step 2 */
AVX_LOAD_NEG(16, "%%ymm15")
"vpxor %%ymm15, %%ymm5, %%ymm5\n\t"
AVX_LOAD_NEG(8, "%%ymm15")
"vpxor %%ymm15, %%ymm0, %%ymm0\n\t"
AVX_MULT("%%ymm5", "%%ymm0", "%%ymm8", "%%ymm9")
"vpxor %%ymm9, %%ymm8, %%ymm15\n\t"
/* Subtract states to compute i, j, k */
"vpsubq %%ymm1, %%ymm0, %%ymm0\n\t"
"leaq %[const_ptr], %%rax\n\t"
"vmovq 7*8(%%rax), %%xmm8\n\t"
"vpunpcklqdq %%xmm8, %%xmm8, %%xmm8\n\t"
"vinserti128 $1, %%xmm8, %%ymm8, %%ymm8\n\t"
"vpxor %%ymm8, %%ymm0, %%ymm0\n\t" /* ymm0 = i */
"vpsubq %%ymm3, %%ymm2, %%ymm2\n\t"
"vmovq 8*8(%%rax), %%xmm8\n\t"
"vpunpcklqdq %%xmm8, %%xmm8, %%xmm8\n\t"
"vinserti128 $1, %%xmm8, %%ymm8, %%ymm8\n\t"
"vpxor %%ymm8, %%ymm2, %%ymm2\n\t" /* ymm2 = j */
"vpsubq %%ymm5, %%ymm4, %%ymm4\n\t"
"vmovq 9*8(%%rax), %%xmm8\n\t"
"vpunpcklqdq %%xmm8, %%xmm8, %%xmm8\n\t"
"vinserti128 $1, %%xmm8, %%ymm8, %%ymm8\n\t"
"vpxor %%ymm8, %%ymm4, %%ymm4\n\t" /* ymm4 = k */
/* Rotations and size subtraction */
"vmovq %[rot], %%xmm8\n\t"
"vmovq %[rot_diff], %%xmm9\n\t"
"vpsllq %%xmm8, %%ymm0, %%ymm1\n\t"
"vpsrlq %%xmm9, %%ymm0, %%ymm0\n\t"
"vpor %%ymm0, %%ymm1, %%ymm0\n\t"
"vpsrlq %%xmm8, %%ymm2, %%ymm3\n\t"
"vpsllq %%xmm9, %%ymm2, %%ymm2\n\t"
"vpor %%ymm2, %%ymm3, %%ymm2\n\t"
"vmovq %[size], %%xmm8\n\t"
"vpunpcklqdq %%xmm8, %%xmm8, %%xmm8\n\t"
"vinserti128 $1, %%xmm8, %%ymm8, %%ymm8\n\t"
"vpsubq %%ymm8, %%ymm4, %%ymm4\n\t"
/* i, j, k corrections */
"vpsubq %%ymm13, %%ymm0, %%ymm0\n\t"
"vpsubq %%ymm14, %%ymm0, %%ymm0\n\t"
"vpsubq %%ymm15, %%ymm2, %%ymm2\n\t"
"vpsubq %%ymm10, %%ymm2, %%ymm2\n\t"
"vpsubq %%ymm11, %%ymm4, %%ymm4\n\t"
"vpsubq %%ymm12, %%ymm4, %%ymm4\n\t"
/* Final multiplications */
AVX_MULT("%%ymm0", "%%ymm2", "%%ymm10", "%%ymm11")
AVX_MULT("%%ymm2", "%%ymm4", "%%ymm12", "%%ymm13")
AVX_MULT("%%ymm4", "%%ymm0", "%%ymm8", "%%ymm9")
"vpxor %%ymm11, %%ymm8, %%ymm0\n\t"
"vpxor %%ymm13, %%ymm10, %%ymm2\n\t"
"vpxor %%ymm9, %%ymm12, %%ymm4\n\t"
/* Multiply by constants 10, 11, 12 */
"vmovq 10*8(%%rax), %%xmm8\n\t"
"vpunpcklqdq %%xmm8, %%xmm8, %%xmm8\n\t"
"vinserti128 $1, %%xmm8, %%ymm8, %%ymm8\n\t"
AVX_MULT("%%ymm0", "%%ymm8", "%%ymm10", "%%ymm11")
"vmovq 11*8(%%rax), %%xmm8\n\t"
"vpunpcklqdq %%xmm8, %%xmm8, %%xmm8\n\t"
"vinserti128 $1, %%xmm8, %%ymm8, %%ymm8\n\t"
AVX_MULT("%%ymm2", "%%ymm8", "%%ymm12", "%%ymm13")
"vmovq 12*8(%%rax), %%xmm8\n\t"
"vpunpcklqdq %%xmm8, %%xmm8, %%xmm8\n\t"
"vinserti128 $1, %%xmm8, %%ymm8, %%ymm8\n\t"
AVX_MULT("%%ymm4", "%%ymm8", "%%ymm6", "%%ymm7")
/* Final digests XOR */
"vpxor %%ymm13, %%ymm10, %%ymm10\n\t"
"vpxor %%ymm6, %%ymm10, %%ymm10\n\t"
"vpxor %%ymm12, %%ymm11, %%ymm11\n\t"
"vpxor %%ymm7, %%ymm11, %%ymm11\n\t"
/* Extract high parts of digests */
"vextracti128 $1, %%ymm10, %%xmm12\n\t"
"vextracti128 $1, %%ymm11, %%xmm13\n\t"
/* Store digest0 */
"movq %[digest0], %%rax\n\t"
"vmovq %%xmm10, (%%rax)\n\t"
"vmovq %%xmm11, 8(%%rax)\n\t"
/* Store digest1 */
"movq %[digest1], %%rcx\n\t"
"vmovhps %%xmm10, (%%rcx)\n\t"
"vmovhps %%xmm11, 8(%%rcx)\n\t"
/* Store digest2 */
"movq %[digest2], %%rdx\n\t"
"vmovq %%xmm12, (%%rdx)\n\t"
"vmovq %%xmm13, 8(%%rdx)\n\t"
/* Store digest3 */
"movq %[digest3], %%rsi\n\t"
"vmovhps %%xmm12, (%%rsi)\n\t"
"vmovhps %%xmm13, 8(%%rsi)\n\t"
: [blocks0] "+r" (blocks0),
[blocks1] "+r" (blocks1),
[blocks2] "+r" (blocks2),
[blocks3] "+r" (blocks3),
[q] "+r" (q)
: [seed0] "m" (seed0),
[seed1] "m" (seed1),
[seed2] "m" (seed2),
[seed3] "m" (seed3),
[digest0] "m" (digest0),
[digest1] "m" (digest1),
[digest2] "m" (digest2),
[digest3] "m" (digest3),
[const_ptr] "m" (MUSEAIR_CONSTANT),
[mask_i] "m" (const_mask_i),
[mask_j] "m" (const_mask_j),
[mask_k] "m" (const_mask_k),
[rot] "m" (rot),
[rot_diff] "m" (rot_diff),
[size] "m" (size)
: "rax", "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11",
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "cc", "memory"
);
}
#else /* !__x86_64__ */
void MuseAirLoongAVX(
const void* data0, const void* data1, const void* data2, const void* data3,
size_t size,
const uint8_t* seed0, const uint8_t* seed1, const uint8_t* seed2, const uint8_t* seed3,
uint8_t* digest0, uint8_t* digest1, uint8_t* digest2, uint8_t* digest3
)
{
MuseAirLoong(data0, size, seed0, digest0);
MuseAirLoong(data1, size, seed1, digest1);
MuseAirLoong(data2, size, seed2, digest2);
MuseAirLoong(data3, size, seed3, digest3);
}
#endif /* __x86_64__ */

486
cmdline/museairsse.c Normal file
View file

@ -0,0 +1,486 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2026 Andrea Mazzoleni
#if defined(__x86_64__)
#define SSE_LOAD(offset, dest) \
"movq " #offset "*8(%[blocks0]), " dest "\n\t" \
"movhps " #offset "*8(%[blocks1]), " dest "\n\t"
#define SSE_LOAD_NEG(offset, dest) \
"movq -" #offset "(%%r8), " dest "\n\t" \
"movhps -" #offset "(%%r9), " dest "\n\t"
#define SSE_MULT(a, b, lo, hi, s0, s1) \
/* 1. Compute B_h in s0 */ \
"movdqa " b ", " s0 "\n\t" \
"psrlq $32, " s0 "\n\t" \
/* 2. Compute P_lh in s1 */ \
"movdqa " a ", " s1 "\n\t" \
"pmuludq " s0 ", " s1 "\n\t" \
/* 3. Compute A_h in hi */ \
"movdqa " a ", " hi "\n\t" \
"psrlq $32, " hi "\n\t" \
/* 4. Compute P_hh in lo */ \
"movdqa " hi ", " lo "\n\t" \
"pmuludq " s0 ", " lo "\n\t" \
/* 5. Compute P_hl in hi */ \
"pmuludq " b ", " hi "\n\t" \
/* 6. Compute P_ll in s0 */ \
"movdqa " a ", " s0 "\n\t" \
"pmuludq " b ", " s0 "\n\t" \
/* 7. M = P_lh + P_hl */ \
"paddq " hi ", " s1 "\n\t" /* s1 = M */ \
/* 8. Move P_hh from lo to hi */ \
"movdqa " lo ", " hi "\n\t" /* hi = P_hh */ \
/* 9. Generate mask 0xffffffff in xmm15 */ \
"pcmpeqd %%xmm15, %%xmm15\n\t" \
"psrlq $32, %%xmm15\n\t" \
/* 10. Split M into s1 = M_low, lo = M_high */ \
"movdqa " s1 ", " lo "\n\t" \
"pand %%xmm15, " s1 "\n\t" /* s1 = M_low */ \
"psrlq $32, " lo "\n\t" /* lo = M_high */ \
/* 11. Split P_ll (in s0) into s0 = P_lll, xmm15 = P_llh (overwriting mask) */ \
"movdqa " s0 ", %%xmm15\n\t" \
"psrlq $32, %%xmm15\n\t" /* xmm15 = P_llh */ \
"pand %%xmm15, " s0 "\n\t" /* s0 = P_lll */ /* Wait! xmm15 contains P_llh which has 0 in high 32 bits, but low 32 bits is P_llh, not 0xffffffff! */ \
/* Ah! We cannot pand with xmm15 because xmm15 is NOT the mask anymore! */ \
/* To fix this, let's just use the shift method for s0! */ \
/* "psllq $32, s0; psrlq $32, s0" is safer! */ \
#define SSE_MULT_FIXED(a, b, lo, hi, s0, s1) \
/* 1. Compute B_h in s0 */ \
"movdqa " b ", " s0 "\n\t" \
"psrlq $32, " s0 "\n\t" \
/* 2. Compute P_lh in s1 */ \
"movdqa " a ", " s1 "\n\t" \
"pmuludq " s0 ", " s1 "\n\t" \
/* 3. Compute A_h in hi */ \
"movdqa " a ", " hi "\n\t" \
"psrlq $32, " hi "\n\t" \
/* 4. Compute P_hh in lo */ \
"movdqa " hi ", " lo "\n\t" \
"pmuludq " s0 ", " lo "\n\t" \
/* 5. Compute P_hl in hi */ \
"pmuludq " b ", " hi "\n\t" \
/* 6. Compute P_ll in s0 */ \
"movdqa " a ", " s0 "\n\t" \
"pmuludq " b ", " s0 "\n\t" \
/* 7. M = P_lh + P_hl */ \
"paddq " hi ", " s1 "\n\t" /* s1 = M */ \
/* 8. Move P_hh from lo to hi */ \
"movdqa " lo ", " hi "\n\t" /* hi = P_hh */ \
/* 9. Generate mask 0xffffffff in xmm15 */ \
"pcmpeqd %%xmm15, %%xmm15\n\t" \
"psrlq $32, %%xmm15\n\t" \
/* 10. Split M into s1 = M_low, lo = M_high */ \
"movdqa " s1 ", " lo "\n\t" \
"pand %%xmm15, " s1 "\n\t" /* s1 = M_low */ \
"psrlq $32, " lo "\n\t" /* lo = M_high */ \
/* 11. Split P_ll (in s0) into s0 = P_lll, xmm15 = P_llh (overwriting mask) */ \
"movdqa " s0 ", %%xmm15\n\t" \
"psrlq $32, %%xmm15\n\t" /* xmm15 = P_llh */ \
"psllq $32, " s0 "\n\t" \
"psrlq $32, " s0 "\n\t" /* s0 = P_lll */ \
/* 12. Compute S1 = P_llh + M_low */ \
"paddq " s1 ", %%xmm15\n\t" /* xmm15 = S1 */ \
/* 13. Split S1 into s1 = C1, xmm15 = S1_l */ \
"movdqa %%xmm15, " s1 "\n\t" \
"psllq $32, %%xmm15\n\t" \
"psrlq $32, %%xmm15\n\t" /* xmm15 = S1_l */ \
"psrlq $32, " s1 "\n\t" /* s1 = C1 */ \
/* 14. Assemble final low (in lo) */ \
"psllq $32, %%xmm15\n\t" \
"paddq " s0 ", %%xmm15\n\t" \
"movdqa %%xmm15, " lo "\n\t" /* lo = final low */ \
/* 15. Split P_hh (in hi) into s0 = P_hhl, hi = P_hhh */ \
"movdqa " hi ", " s0 "\n\t" \
"psllq $32, " s0 "\n\t" \
"psrlq $32, " s0 "\n\t" /* s0 = P_hhl */ \
"psrlq $32, " hi "\n\t" /* hi = P_hhh */ \
/* 16. Compute final high (in hi) */ \
"paddq " lo ", " s0 "\n\t" /* s0 = M_high + P_hhl */ \
"paddq " s1 ", " s0 "\n\t" /* s0 = M_high + P_hhl + C1 */ \
"psllq $32, " hi "\n\t" \
"paddq " s0 ", " hi "\n\t" /* hi = final high */
void MuseAirLoongSSE(
const void* data0, const void* data1,
size_t size,
const uint8_t* seed0, const uint8_t* seed1,
uint8_t* digest0, uint8_t* digest1
)
{
uint64_t buf0[12];
uint64_t buf1[12];
const uint8_t* blocks0 = data0;
const uint8_t* blocks1 = data1;
size_t q = size;
if (q < 32) {
memset(buf0, 0, 32);
memset(buf1, 0, 32);
if (q > 0) {
memcpy(buf0, blocks0, q);
memcpy(buf1, blocks1, q);
}
blocks0 = (const uint8_t*)buf0;
blocks1 = (const uint8_t*)buf1;
q = 32;
}
uint64_t rot = size & 63;
uint64_t rot_diff = 64 - rot;
static const uint64_t const_mask_i = 01555555555555555555555ULL;
static const uint64_t const_mask_j = 01333333333333333333333ULL;
static const uint64_t const_mask_k = 00666666666666666666666ULL;
__asm__ __volatile__ (
/* Load seed0 and seed1 */
"movq %[seed0], %%rax\n\t"
"movq (%%rax), %%xmm9\n\t"
"movq %[seed1], %%rcx\n\t"
"movhps (%%rcx), %%xmm9\n\t" /* xmm9 = seed_a */
"movq %[seed0], %%rax\n\t"
"movq 8(%%rax), %%xmm10\n\t"
"movq %[seed1], %%rcx\n\t"
"movhps 8(%%rcx), %%xmm10\n\t" /* xmm10 = seed_b */
/* Load and duplicate masks */
"movq %[mask_i], %%xmm12\n\t"
"punpcklqdq %%xmm12, %%xmm12\n\t"
"movq %[mask_j], %%xmm13\n\t"
"punpcklqdq %%xmm13, %%xmm13\n\t"
"movq %[mask_k], %%xmm14\n\t"
"punpcklqdq %%xmm14, %%xmm14\n\t"
/* Initialize states */
"leaq %[const_ptr], %%rax\n\t"
/* state0 */
"movq 0*8(%%rax), %%xmm0\n\t"
"punpcklqdq %%xmm0, %%xmm0\n\t"
"movdqa %%xmm9, %%xmm15\n\t"
"pand %%xmm12, %%xmm15\n\t"
"pxor %%xmm15, %%xmm0\n\t"
/* state1 */
"movq 1*8(%%rax), %%xmm1\n\t"
"punpcklqdq %%xmm1, %%xmm1\n\t"
"movdqa %%xmm10, %%xmm15\n\t"
"pand %%xmm13, %%xmm15\n\t"
"pxor %%xmm15, %%xmm1\n\t"
/* state2 */
"movq 2*8(%%rax), %%xmm2\n\t"
"punpcklqdq %%xmm2, %%xmm2\n\t"
"movdqa %%xmm9, %%xmm15\n\t"
"pand %%xmm14, %%xmm15\n\t"
"pxor %%xmm15, %%xmm2\n\t"
/* state3 */
"movq 3*8(%%rax), %%xmm3\n\t"
"punpcklqdq %%xmm3, %%xmm3\n\t"
"movdqa %%xmm10, %%xmm15\n\t"
"pand %%xmm12, %%xmm15\n\t"
"pxor %%xmm15, %%xmm3\n\t"
/* state4 */
"movq 4*8(%%rax), %%xmm4\n\t"
"punpcklqdq %%xmm4, %%xmm4\n\t"
"movdqa %%xmm9, %%xmm15\n\t"
"pand %%xmm13, %%xmm15\n\t"
"pxor %%xmm15, %%xmm4\n\t"
/* state5 */
"movq 5*8(%%rax), %%xmm5\n\t"
"punpcklqdq %%xmm5, %%xmm5\n\t"
"movdqa %%xmm10, %%xmm15\n\t"
"pand %%xmm14, %%xmm15\n\t"
"pxor %%xmm15, %%xmm5\n\t"
/* lo5 and hi5 */
"movq 6*8(%%rax), %%xmm6\n\t"
"punpcklqdq %%xmm6, %%xmm6\n\t"
"movdqa %%xmm6, %%xmm7\n\t"
/* Conditional loop */
"cmp $96, %[q]\n\t"
"jbe 3f\n\t"
"1:\n\t"
/* Loop step idx = 0 */
SSE_LOAD(0, "%%xmm15")
"pxor %%xmm15, %%xmm0\n\t"
SSE_LOAD(1, "%%xmm15")
"pxor %%xmm15, %%xmm1\n\t"
SSE_MULT_FIXED("%%xmm0", "%%xmm1", "%%xmm8", "%%xmm9", "%%xmm10", "%%xmm11")
"movdqa %%xmm6, %%xmm0\n\t"
"pxor %%xmm9, %%xmm0\n\t"
"movdqa %%xmm8, %%xmm10\n\t"
/* Loop step idx = 1 */
SSE_LOAD(2, "%%xmm15")
"pxor %%xmm15, %%xmm1\n\t"
SSE_LOAD(3, "%%xmm15")
"pxor %%xmm15, %%xmm2\n\t"
SSE_MULT_FIXED("%%xmm1", "%%xmm2", "%%xmm8", "%%xmm9", "%%xmm11", "%%xmm15")
"movdqa %%xmm10, %%xmm1\n\t"
"pxor %%xmm9, %%xmm1\n\t"
"movdqa %%xmm8, %%xmm10\n\t"
/* Loop step idx = 2 */
SSE_LOAD(4, "%%xmm15")
"pxor %%xmm15, %%xmm2\n\t"
SSE_LOAD(5, "%%xmm15")
"pxor %%xmm15, %%xmm3\n\t"
SSE_MULT_FIXED("%%xmm2", "%%xmm3", "%%xmm8", "%%xmm9", "%%xmm11", "%%xmm15")
"movdqa %%xmm10, %%xmm2\n\t"
"pxor %%xmm9, %%xmm2\n\t"
"movdqa %%xmm8, %%xmm10\n\t"
/* Loop step idx = 3 */
SSE_LOAD(6, "%%xmm15")
"pxor %%xmm15, %%xmm3\n\t"
SSE_LOAD(7, "%%xmm15")
"pxor %%xmm15, %%xmm4\n\t"
SSE_MULT_FIXED("%%xmm3", "%%xmm4", "%%xmm8", "%%xmm9", "%%xmm11", "%%xmm15")
"movdqa %%xmm10, %%xmm3\n\t"
"pxor %%xmm9, %%xmm3\n\t"
"movdqa %%xmm8, %%xmm10\n\t"
/* Loop step idx = 4 */
SSE_LOAD(8, "%%xmm15")
"pxor %%xmm15, %%xmm4\n\t"
SSE_LOAD(9, "%%xmm15")
"pxor %%xmm15, %%xmm5\n\t"
SSE_MULT_FIXED("%%xmm4", "%%xmm5", "%%xmm8", "%%xmm9", "%%xmm11", "%%xmm15")
"movdqa %%xmm10, %%xmm4\n\t"
"pxor %%xmm9, %%xmm4\n\t"
"movdqa %%xmm8, %%xmm10\n\t"
/* Loop step idx = 5 */
SSE_LOAD(10, "%%xmm15")
"pxor %%xmm15, %%xmm5\n\t"
SSE_LOAD(11, "%%xmm15")
"pxor %%xmm15, %%xmm0\n\t"
SSE_MULT_FIXED("%%xmm5", "%%xmm0", "%%xmm8", "%%xmm9", "%%xmm11", "%%xmm15")
"movdqa %%xmm10, %%xmm5\n\t"
"pxor %%xmm9, %%xmm5\n\t"
"movdqa %%xmm8, %%xmm6\n\t"
"movdqa %%xmm9, %%xmm7\n\t"
"add $96, %[blocks0]\n\t"
"add $96, %[blocks1]\n\t"
"sub $96, %[q]\n\t"
"cmp $96, %[q]\n\t"
"ja 1b\n\t"
"pxor %%xmm6, %%xmm0\n\t"
"3:\n\t"
/* Tail */
"movdqa %%xmm1, %%xmm10\n\t" /* xor0 = state1 */
"movdqa %%xmm2, %%xmm11\n\t" /* xor1 = state2 */
"movdqa %%xmm3, %%xmm12\n\t" /* xor2 = state3 */
"movdqa %%xmm4, %%xmm13\n\t" /* xor3 = state4 */
"cmp $32, %[q]\n\t"
"jbe 4f\n\t"
SSE_LOAD(0, "%%xmm15")
"pxor %%xmm15, %%xmm0\n\t"
SSE_LOAD(1, "%%xmm15")
"pxor %%xmm15, %%xmm1\n\t"
SSE_MULT_FIXED("%%xmm0", "%%xmm1", "%%xmm8", "%%xmm9", "%%xmm14", "%%xmm15")
"movdqa %%xmm8, %%xmm10\n\t"
"pxor %%xmm9, %%xmm10\n\t"
"cmp $48, %[q]\n\t"
"jbe 4f\n\t"
SSE_LOAD(2, "%%xmm15")
"pxor %%xmm15, %%xmm1\n\t"
SSE_LOAD(3, "%%xmm15")
"pxor %%xmm15, %%xmm2\n\t"
SSE_MULT_FIXED("%%xmm1", "%%xmm2", "%%xmm8", "%%xmm9", "%%xmm14", "%%xmm15")
"movdqa %%xmm8, %%xmm11\n\t"
"pxor %%xmm9, %%xmm11\n\t"
"cmp $64, %[q]\n\t"
"jbe 4f\n\t"
SSE_LOAD(4, "%%xmm15")
"pxor %%xmm15, %%xmm2\n\t"
SSE_LOAD(5, "%%xmm15")
"pxor %%xmm15, %%xmm3\n\t"
SSE_MULT_FIXED("%%xmm2", "%%xmm3", "%%xmm8", "%%xmm9", "%%xmm14", "%%xmm15")
"movdqa %%xmm8, %%xmm12\n\t"
"pxor %%xmm9, %%xmm12\n\t"
"cmp $80, %[q]\n\t"
"jbe 4f\n\t"
SSE_LOAD(6, "%%xmm15")
"pxor %%xmm15, %%xmm3\n\t"
SSE_LOAD(7, "%%xmm15")
"pxor %%xmm15, %%xmm4\n\t"
SSE_MULT_FIXED("%%xmm3", "%%xmm4", "%%xmm8", "%%xmm9", "%%xmm14", "%%xmm15")
"movdqa %%xmm8, %%xmm13\n\t"
"pxor %%xmm9, %%xmm13\n\t"
"4:\n\t"
/* Compute end pointers */
"movq %[blocks0], %%r8\n\t"
"add %[q], %%r8\n\t"
"movq %[blocks1], %%r9\n\t"
"add %[q], %%r9\n\t"
/* Unconditional tail step 1 */
SSE_LOAD_NEG(32, "%%xmm15")
"pxor %%xmm15, %%xmm4\n\t"
SSE_LOAD_NEG(24, "%%xmm15")
"pxor %%xmm15, %%xmm5\n\t"
SSE_MULT_FIXED("%%xmm4", "%%xmm5", "%%xmm8", "%%xmm9", "%%xmm14", "%%xmm15")
"movdqa %%xmm8, %%xmm14\n\t"
"pxor %%xmm9, %%xmm14\n\t"
/* Unconditional tail step 2 */
SSE_LOAD_NEG(16, "%%xmm15")
"pxor %%xmm15, %%xmm5\n\t"
SSE_LOAD_NEG(8, "%%xmm15")
"pxor %%xmm15, %%xmm0\n\t"
SSE_MULT_FIXED("%%xmm5", "%%xmm0", "%%xmm8", "%%xmm9", "%%xmm12", "%%xmm15")
"movdqa %%xmm8, %%xmm15\n\t"
"pxor %%xmm9, %%xmm15\n\t"
/* Subtract states to compute i, j, k */
"psubq %%xmm1, %%xmm0\n\t"
"leaq %[const_ptr], %%rax\n\t"
"movq 7*8(%%rax), %%xmm8\n\t"
"punpcklqdq %%xmm8, %%xmm8\n\t"
"pxor %%xmm8, %%xmm0\n\t" /* xmm0 = i */
"psubq %%xmm3, %%xmm2\n\t"
"movq 8*8(%%rax), %%xmm8\n\t"
"punpcklqdq %%xmm8, %%xmm8\n\t"
"pxor %%xmm8, %%xmm2\n\t" /* xmm2 = j */
"psubq %%xmm5, %%xmm4\n\t"
"movq 9*8(%%rax), %%xmm8\n\t"
"punpcklqdq %%xmm8, %%xmm8\n\t"
"pxor %%xmm8, %%xmm4\n\t" /* xmm4 = k */
/* Rotations and size subtraction */
"movq %[rot], %%xmm8\n\t"
"movq %[rot_diff], %%xmm9\n\t"
"movdqa %%xmm0, %%xmm1\n\t"
"psllq %%xmm8, %%xmm0\n\t"
"psrlq %%xmm9, %%xmm1\n\t"
"por %%xmm1, %%xmm0\n\t"
"movdqa %%xmm2, %%xmm3\n\t"
"psrlq %%xmm8, %%xmm2\n\t"
"psllq %%xmm9, %%xmm3\n\t"
"por %%xmm3, %%xmm2\n\t"
"movq %[size], %%xmm8\n\t"
"punpcklqdq %%xmm8, %%xmm8\n\t"
"psubq %%xmm8, %%xmm4\n\t"
/* i, j, k corrections */
"psubq %%xmm13, %%xmm0\n\t"
"psubq %%xmm14, %%xmm0\n\t"
"psubq %%xmm15, %%xmm2\n\t"
"psubq %%xmm10, %%xmm2\n\t"
"psubq %%xmm11, %%xmm4\n\t"
"psubq %%xmm12, %%xmm4\n\t"
/* Final multiplications */
SSE_MULT_FIXED("%%xmm0", "%%xmm2", "%%xmm10", "%%xmm11", "%%xmm8", "%%xmm9")
SSE_MULT_FIXED("%%xmm2", "%%xmm4", "%%xmm12", "%%xmm13", "%%xmm8", "%%xmm9")
SSE_MULT_FIXED("%%xmm4", "%%xmm0", "%%xmm8", "%%xmm9", "%%xmm14", "%%xmm15")
"movdqa %%xmm8, %%xmm0\n\t"
"pxor %%xmm11, %%xmm0\n\t"
"movdqa %%xmm10, %%xmm2\n\t"
"pxor %%xmm13, %%xmm2\n\t"
"movdqa %%xmm12, %%xmm4\n\t"
"pxor %%xmm9, %%xmm4\n\t"
/* Multiply by constants 10, 11, 12 */
"leaq %[const_ptr], %%rax\n\t"
"movq 10*8(%%rax), %%xmm8\n\t"
"punpcklqdq %%xmm8, %%xmm8\n\t"
SSE_MULT_FIXED("%%xmm0", "%%xmm8", "%%xmm10", "%%xmm11", "%%xmm12", "%%xmm13")
"leaq %[const_ptr], %%rax\n\t"
"movq 11*8(%%rax), %%xmm8\n\t"
"punpcklqdq %%xmm8, %%xmm8\n\t"
SSE_MULT_FIXED("%%xmm2", "%%xmm8", "%%xmm12", "%%xmm13", "%%xmm10", "%%xmm11")
"leaq %[const_ptr], %%rax\n\t"
"movq 12*8(%%rax), %%xmm8\n\t"
"punpcklqdq %%xmm8, %%xmm8\n\t"
SSE_MULT_FIXED("%%xmm4", "%%xmm8", "%%xmm6", "%%xmm7", "%%xmm10", "%%xmm11")
/* Final digests XOR */
"pxor %%xmm13, %%xmm10\n\t"
"pxor %%xmm6, %%xmm10\n\t"
"pxor %%xmm12, %%xmm11\n\t"
"pxor %%xmm7, %%xmm11\n\t"
/* Store back digests */
"movq %[digest0], %%rax\n\t"
"movq %%xmm10, (%%rax)\n\t"
"movq %%xmm11, 8(%%rax)\n\t"
"movq %[digest1], %%rcx\n\t"
"movhps %%xmm10, (%%rcx)\n\t"
"movhps %%xmm11, 8(%%rcx)\n\t"
: [blocks0] "+r" (blocks0),
[blocks1] "+r" (blocks1),
[q] "+r" (q)
: [seed0] "m" (seed0),
[seed1] "m" (seed1),
[digest0] "m" (digest0),
[digest1] "m" (digest1),
[const_ptr] "m" (MUSEAIR_CONSTANT),
[mask_i] "m" (const_mask_i),
[mask_j] "m" (const_mask_j),
[mask_k] "m" (const_mask_k),
[rot] "m" (rot),
[rot_diff] "m" (rot_diff),
[size] "m" (size)
: "rax", "rcx", "rdx", "r8", "r9",
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "cc", "memory"
);
}
#else /* !__x86_64__ */
void MuseAirLoongSSE(
const void* data0, const void* data1,
size_t size,
const uint8_t* seed0, const uint8_t* seed1,
uint8_t* digest0, uint8_t* digest1
)
{
MuseAirLoong(data0, size, seed0, digest0);
MuseAirLoong(data1, size, seed1, digest1);
}
#endif /* __x86_64__ */

View file

@ -235,6 +235,132 @@ static void test_hash(void)
}
}
for (i = 0; TEST_SPOOKY2[i].data; ++i) {
unsigned char digest0[HASH_MAX];
unsigned char digest1[HASH_MAX];
unsigned char buffer0[4096];
unsigned char buffer1[4096];
unsigned char seed0[HASH_MAX];
unsigned char seed1[HASH_MAX];
int len = TEST_SPOOKY2[i].len;
unsigned k;
if (len > 4096) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Test vector too long\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
for (k = 0; TEST_SPOOKY2[k].data; ++k) {
if (TEST_SPOOKY2[k].len == len && k != i) {
break;
}
}
if (!TEST_SPOOKY2[k].data) {
k = i;
}
memcpy(buffer0, TEST_SPOOKY2[i].data, len);
memcpy(seed0, TEST_SPOOKY2[i].seed, HASH_MAX);
memcpy(buffer1, TEST_SPOOKY2[k].data, len);
memcpy(seed1, TEST_SPOOKY2[k].seed, HASH_MAX);
SpookyHash128SSE(buffer0, buffer1, len, seed0, seed1, digest0, digest1);
if (memcmp(digest0, TEST_SPOOKY2[i].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed SpookyHash128SSE test 0 on vector %d\n", i);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (memcmp(digest1, TEST_SPOOKY2[k].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed SpookyHash128SSE test 1 on vector %d and %d\n", i, k);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
/* SpookyHash128AVX self-test */
for (i = 0; TEST_SPOOKY2[i].data; ++i) {
unsigned char buffer0[4096];
unsigned char buffer1[4096];
unsigned char buffer2[4096];
unsigned char buffer3[4096];
unsigned char seed0[HASH_MAX];
unsigned char seed1[HASH_MAX];
unsigned char seed2[HASH_MAX];
unsigned char seed3[HASH_MAX];
unsigned char digest0[HASH_MAX];
unsigned char digest1[HASH_MAX];
unsigned char digest2[HASH_MAX];
unsigned char digest3[HASH_MAX];
int len = TEST_SPOOKY2[i].len;
unsigned k, l, m;
for (k = 0; TEST_SPOOKY2[k].data; ++k) {
if (TEST_SPOOKY2[k].len == len && k != i) {
break;
}
}
if (!TEST_SPOOKY2[k].data) k = i;
for (l = 0; TEST_SPOOKY2[l].data; ++l) {
if (TEST_SPOOKY2[l].len == len && l != i && l != k) {
break;
}
}
if (!TEST_SPOOKY2[l].data) l = i;
for (m = 0; TEST_SPOOKY2[m].data; ++m) {
if (TEST_SPOOKY2[m].len == len && m != i && m != k && m != l) {
break;
}
}
if (!TEST_SPOOKY2[m].data) m = i;
memcpy(buffer0, TEST_SPOOKY2[i].data, len);
memcpy(seed0, TEST_SPOOKY2[i].seed, HASH_MAX);
memcpy(buffer1, TEST_SPOOKY2[k].data, len);
memcpy(seed1, TEST_SPOOKY2[k].seed, HASH_MAX);
memcpy(buffer2, TEST_SPOOKY2[l].data, len);
memcpy(seed2, TEST_SPOOKY2[l].seed, HASH_MAX);
memcpy(buffer3, TEST_SPOOKY2[m].data, len);
memcpy(seed3, TEST_SPOOKY2[m].seed, HASH_MAX);
SpookyHash128AVX(buffer0, buffer1, buffer2, buffer3, len, seed0, seed1, seed2, seed3, digest0, digest1, digest2, digest3);
if (memcmp(digest0, TEST_SPOOKY2[i].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed SpookyHash128AVX test 0 on vector %d\n", i);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (memcmp(digest1, TEST_SPOOKY2[k].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed SpookyHash128AVX test 1 on vector %d and %d\n", i, k);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (memcmp(digest2, TEST_SPOOKY2[l].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed SpookyHash128AVX test 2 on vector %d and %d\n", i, l);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (memcmp(digest3, TEST_SPOOKY2[m].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed SpookyHash128AVX test 3 on vector %d and %d\n", i, m);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
for (i = 0; TEST_METRO[i].data; ++i) {
unsigned char digest[HASH_MAX];
memcpy(buffer_aligned, TEST_METRO[i].data, TEST_METRO[i].len);
@ -261,6 +387,140 @@ static void test_hash(void)
}
}
/* MuseAir SSE self-test */
for (i = 0; TEST_MUSEAIR[i].data; ++i) {
unsigned char digest0[HASH_MAX];
unsigned char digest1[HASH_MAX];
unsigned char buffer0[4096];
unsigned char buffer1[4096];
unsigned char seed0[HASH_MAX];
unsigned char seed1[HASH_MAX];
int len = TEST_MUSEAIR[i].len;
unsigned k;
if (len > 4096) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Test vector too long\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
for (k = 0; TEST_MUSEAIR[k].data; ++k) {
if (TEST_MUSEAIR[k].len == len && k != i) {
break;
}
}
if (!TEST_MUSEAIR[k].data) {
k = i;
}
memcpy(buffer0, TEST_MUSEAIR[i].data, len);
memcpy(seed0, TEST_MUSEAIR[i].seed, HASH_MAX);
memcpy(buffer1, TEST_MUSEAIR[k].data, len);
memcpy(seed1, TEST_MUSEAIR[k].seed, HASH_MAX);
MuseAirLoongSSE(buffer0, buffer1, len, seed0, seed1, digest0, digest1);
if (memcmp(digest0, TEST_MUSEAIR[i].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed MuseAirLoongSSE test 0 on vector %d\n", i);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (memcmp(digest1, TEST_MUSEAIR[k].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed MuseAirLoongSSE test 1 on vector %d and %d\n", i, k);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
/* MuseAir AVX self-test */
for (i = 0; TEST_MUSEAIR[i].data; ++i) {
unsigned char buffer0[4096];
unsigned char buffer1[4096];
unsigned char buffer2[4096];
unsigned char buffer3[4096];
unsigned char seed0[HASH_MAX];
unsigned char seed1[HASH_MAX];
unsigned char seed2[HASH_MAX];
unsigned char seed3[HASH_MAX];
unsigned char digest0[HASH_MAX];
unsigned char digest1[HASH_MAX];
unsigned char digest2[HASH_MAX];
unsigned char digest3[HASH_MAX];
int len = TEST_MUSEAIR[i].len;
unsigned k, l, m;
if (len > 4096) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Test vector too long\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
for (k = 0; TEST_MUSEAIR[k].data; ++k) {
if (TEST_MUSEAIR[k].len == len && k != i) {
break;
}
}
if (!TEST_MUSEAIR[k].data) k = i;
for (l = 0; TEST_MUSEAIR[l].data; ++l) {
if (TEST_MUSEAIR[l].len == len && l != i && l != k) {
break;
}
}
if (!TEST_MUSEAIR[l].data) l = i;
for (m = 0; TEST_MUSEAIR[m].data; ++m) {
if (TEST_MUSEAIR[m].len == len && m != i && m != k && m != l) {
break;
}
}
if (!TEST_MUSEAIR[m].data) m = i;
memcpy(buffer0, TEST_MUSEAIR[i].data, len);
memcpy(seed0, TEST_MUSEAIR[i].seed, HASH_MAX);
memcpy(buffer1, TEST_MUSEAIR[k].data, len);
memcpy(seed1, TEST_MUSEAIR[k].seed, HASH_MAX);
memcpy(buffer2, TEST_MUSEAIR[l].data, len);
memcpy(seed2, TEST_MUSEAIR[l].seed, HASH_MAX);
memcpy(buffer3, TEST_MUSEAIR[m].data, len);
memcpy(seed3, TEST_MUSEAIR[m].seed, HASH_MAX);
MuseAirLoongAVX(buffer0, buffer1, buffer2, buffer3, len, seed0, seed1, seed2, seed3, digest0, digest1, digest2, digest3);
if (memcmp(digest0, TEST_MUSEAIR[i].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed MuseAirLoongAVX test 0 on vector %d\n", i);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (memcmp(digest1, TEST_MUSEAIR[k].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed MuseAirLoongAVX test 1 on vector %d and %d\n", i, k);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (memcmp(digest2, TEST_MUSEAIR[l].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed MuseAirLoongAVX test 2 on vector %d and %d\n", i, l);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (memcmp(digest3, TEST_MUSEAIR[m].digest, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal(EINTERNAL, "Failed MuseAirLoongAVX test 3 on vector %d and %d\n", i, m);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
free(buffer_alloc);
free(seed_alloc);
}

View file

@ -154,8 +154,12 @@ void speed_hash(int nd, void** v, int size, int delta, int period)
printf("%8s", "best");
printf("%8s", "murmur3");
printf("%8s", "spooky2");
printf("%8s", "spk2sse");
printf("%8s", "spk2avx");
printf("%8s", "metro");
printf("%8s", "museair");
printf("%8s", "musesse");
printf("%8s", "museavx");
printf("\n");
printf("%8s", "hash");
@ -178,6 +182,38 @@ void speed_hash(int nd, void** v, int size, int delta, int period)
printf("%8" PRIu64, ds / dt);
fflush(stdout);
if (raid_cpu_has_sse2()) {
SPEED_START {
for (j = 0; j < nd - 1; j += 2) {
SpookyHash128SSE(v[j], v[j + 1], size, seed, seed, digest, digest);
}
if (j < nd) {
SpookyHash128(v[j], size, seed, digest);
}
} SPEED_STOP
printf("%8" PRIu64, ds / dt);
} else {
printf("%8s", "-");
}
fflush(stdout);
if (raid_cpu_has_avx2()) {
SPEED_START {
for (j = 0; j < nd - 3; j += 4) {
SpookyHash128AVX(v[j], v[j + 1], v[j + 2], v[j + 3], size, seed, seed, seed, seed, digest, digest, digest, digest);
}
for (; j < nd; ++j) {
SpookyHash128(v[j], size, seed, digest);
}
} SPEED_STOP
printf("%8" PRIu64, ds / dt);
} else {
printf("%8s", "-");
}
fflush(stdout);
SPEED_START {
for (j = 0; j < nd; ++j)
memhash(HASH_METRO, seed, digest, v[j], size);
@ -192,6 +228,38 @@ void speed_hash(int nd, void** v, int size, int delta, int period)
} SPEED_STOP
printf("%8" PRIu64, ds / dt);
fflush(stdout);
if (raid_cpu_has_sse2()) {
SPEED_START {
for (j = 0; j < nd - 1; j += 2) {
MuseAirLoongSSE(v[j], v[j + 1], size, seed, seed, digest, digest);
}
if (j < nd) {
MuseAirLoong(v[j], size, seed, digest);
}
} SPEED_STOP
printf("%8" PRIu64, ds / dt);
} else {
printf("%8s", "-");
}
fflush(stdout);
if (raid_cpu_has_avx2()) {
SPEED_START {
for (j = 0; j < nd - 3; j += 4) {
MuseAirLoongAVX(v[j], v[j + 1], v[j + 2], v[j + 3], size, seed, seed, seed, seed, digest, digest, digest, digest);
}
for (; j < nd; ++j) {
MuseAirLoong(v[j], size, seed, digest);
}
} SPEED_STOP
printf("%8" PRIu64, ds / dt);
} else {
printf("%8s", "-");
}
printf("\n");
printf("\n");
}

324
cmdline/spooky2avx.c Normal file
View file

@ -0,0 +1,324 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2013 Andrea Mazzoleni
#if defined(__x86_64__)
#ifndef sc_numVars
#define sc_numVars 12
#endif
#ifndef sc_blockSize
#define sc_blockSize (sc_numVars * 8)
#endif
#ifndef sc_const
#define sc_const 0xdeadbeefdeadbeefLL
#endif
#define ASM_STEP_AVX2(idx, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, r, r_diff) \
"vmovq " #idx "*8(%[blocks0]), %%xmm12\n\t" \
"vmovhps " #idx "*8(%[blocks1]), %%xmm12, %%xmm12\n\t" \
"vmovq " #idx "*8(%[blocks2]), %%xmm13\n\t" \
"vmovhps " #idx "*8(%[blocks3]), %%xmm13, %%xmm13\n\t" \
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t" \
"vpaddq %%ymm12, " s0 ", " s0 "\n\t" \
"vpxor " s10 ", " s2 ", " s2 "\n\t" \
"vpxor " s0 ", " s11 ", " s11 "\n\t" \
"vmovdqa " s0 ", %%ymm13\n\t" \
"vpsllq $" #r ", " s0 ", " s0 "\n\t" \
"vpsrlq $" #r_diff ", %%ymm13, %%ymm13\n\t" \
"vpor %%ymm13, " s0 ", " s0 "\n\t" \
"vpaddq " s1 ", " s11 ", " s11 "\n\t"
#define ASM_MIX_AVX2 \
ASM_STEP_AVX2(0, "%%ymm0", "%%ymm1", "%%ymm2", "%%ymm3", "%%ymm4", "%%ymm5", "%%ymm6", "%%ymm7", "%%ymm8", "%%ymm9", "%%ymm10", "%%ymm11", 11, 53) \
ASM_STEP_AVX2(1, "%%ymm1", "%%ymm2", "%%ymm3", "%%ymm4", "%%ymm5", "%%ymm6", "%%ymm7", "%%ymm8", "%%ymm9", "%%ymm10", "%%ymm11", "%%ymm0", 32, 32) \
ASM_STEP_AVX2(2, "%%ymm2", "%%ymm3", "%%ymm4", "%%ymm5", "%%ymm6", "%%ymm7", "%%ymm8", "%%ymm9", "%%ymm10", "%%ymm11", "%%ymm0", "%%ymm1", 43, 21) \
ASM_STEP_AVX2(3, "%%ymm3", "%%ymm4", "%%ymm5", "%%ymm6", "%%ymm7", "%%ymm8", "%%ymm9", "%%ymm10", "%%ymm11", "%%ymm0", "%%ymm1", "%%ymm2", 31, 33) \
ASM_STEP_AVX2(4, "%%ymm4", "%%ymm5", "%%ymm6", "%%ymm7", "%%ymm8", "%%ymm9", "%%ymm10", "%%ymm11", "%%ymm0", "%%ymm1", "%%ymm2", "%%ymm3", 17, 47) \
ASM_STEP_AVX2(5, "%%ymm5", "%%ymm6", "%%ymm7", "%%ymm8", "%%ymm9", "%%ymm10", "%%ymm11", "%%ymm0", "%%ymm1", "%%ymm2", "%%ymm3", "%%ymm4", 28, 36) \
ASM_STEP_AVX2(6, "%%ymm6", "%%ymm7", "%%ymm8", "%%ymm9", "%%ymm10", "%%ymm11", "%%ymm0", "%%ymm1", "%%ymm2", "%%ymm3", "%%ymm4", "%%ymm5", 39, 25) \
ASM_STEP_AVX2(7, "%%ymm7", "%%ymm8", "%%ymm9", "%%ymm10", "%%ymm11", "%%ymm0", "%%ymm1", "%%ymm2", "%%ymm3", "%%ymm4", "%%ymm5", "%%ymm6", 57, 7) \
ASM_STEP_AVX2(8, "%%ymm8", "%%ymm9", "%%ymm10", "%%ymm11", "%%ymm0", "%%ymm1", "%%ymm2", "%%ymm3", "%%ymm4", "%%ymm5", "%%ymm6", "%%ymm7", 55, 9) \
ASM_STEP_AVX2(9, "%%ymm9", "%%ymm10", "%%ymm11", "%%ymm0", "%%ymm1", "%%ymm2", "%%ymm3", "%%ymm4", "%%ymm5", "%%ymm6", "%%ymm7", "%%ymm8", 54, 10) \
ASM_STEP_AVX2(10, "%%ymm10", "%%ymm11", "%%ymm0", "%%ymm1", "%%ymm2", "%%ymm3", "%%ymm4", "%%ymm5", "%%ymm6", "%%ymm7", "%%ymm8", "%%ymm9", 22, 42) \
ASM_STEP_AVX2(11, "%%ymm11", "%%ymm0", "%%ymm1", "%%ymm2", "%%ymm3", "%%ymm4", "%%ymm5", "%%ymm6", "%%ymm7", "%%ymm8", "%%ymm9", "%%ymm10", 46, 18)
#define ASM_END_STEP_AVX2(s1, s11, s2, r, r_diff) \
"vpaddq " s1 ", " s11 ", " s11 "\n\t" \
"vpxor " s11 ", " s2 ", " s2 "\n\t" \
"vmovdqa " s1 ", %%ymm13\n\t" \
"vpsllq $" #r ", " s1 ", " s1 "\n\t" \
"vpsrlq $" #r_diff ", %%ymm13, %%ymm13\n\t" \
"vpor %%ymm13, " s1 ", " s1 "\n\t"
#define ASM_END_PARTIAL_AVX2 \
ASM_END_STEP_AVX2("%%ymm1", "%%ymm11", "%%ymm2", 44, 20) \
ASM_END_STEP_AVX2("%%ymm2", "%%ymm0", "%%ymm3", 15, 49) \
ASM_END_STEP_AVX2("%%ymm3", "%%ymm1", "%%ymm4", 34, 30) \
ASM_END_STEP_AVX2("%%ymm4", "%%ymm2", "%%ymm5", 21, 43) \
ASM_END_STEP_AVX2("%%ymm5", "%%ymm3", "%%ymm6", 38, 26) \
ASM_END_STEP_AVX2("%%ymm6", "%%ymm4", "%%ymm7", 33, 31) \
ASM_END_STEP_AVX2("%%ymm7", "%%ymm5", "%%ymm8", 10, 54) \
ASM_END_STEP_AVX2("%%ymm8", "%%ymm6", "%%ymm9", 13, 51) \
ASM_END_STEP_AVX2("%%ymm9", "%%ymm7", "%%ymm10", 38, 26) \
ASM_END_STEP_AVX2("%%ymm10", "%%ymm8", "%%ymm11", 53, 11) \
ASM_END_STEP_AVX2("%%ymm11", "%%ymm9", "%%ymm0", 42, 22) \
ASM_END_STEP_AVX2("%%ymm0", "%%ymm10", "%%ymm1", 54, 10)
void SpookyHash128AVX(
const void* data0, const void* data1, const void* data2, const void* data3,
size_t size,
const uint8_t* seed0, const uint8_t* seed1, const uint8_t* seed2, const uint8_t* seed3,
uint8_t* digest0, uint8_t* digest1, uint8_t* digest2, uint8_t* digest3
)
{
uint64_t buf0[sc_numVars];
uint64_t buf1[sc_numVars];
uint64_t buf2[sc_numVars];
uint64_t buf3[sc_numVars];
size_t nblocks;
const uint8_t* blocks0;
const uint8_t* blocks1;
const uint8_t* blocks2;
const uint8_t* blocks3;
const uint8_t* end0;
size_t size_remainder;
static const uint64_t sc_const_val = sc_const;
nblocks = size / sc_blockSize;
blocks0 = (const uint8_t*)data0;
blocks1 = (const uint8_t*)data1;
blocks2 = (const uint8_t*)data2;
blocks3 = (const uint8_t*)data3;
end0 = blocks0 + nblocks * sc_blockSize;
/* tail data is computed beforehand */
size_remainder = size - nblocks * sc_blockSize;
memcpy(buf0, blocks0 + nblocks * sc_blockSize, size_remainder);
memset(((uint8_t*)buf0) + size_remainder, 0, sc_blockSize - size_remainder);
((uint8_t*)buf0)[sc_blockSize - 1] = size_remainder;
memcpy(buf1, blocks1 + nblocks * sc_blockSize, size_remainder);
memset(((uint8_t*)buf1) + size_remainder, 0, sc_blockSize - size_remainder);
((uint8_t*)buf1)[sc_blockSize - 1] = size_remainder;
memcpy(buf2, blocks2 + nblocks * sc_blockSize, size_remainder);
memset(((uint8_t*)buf2) + size_remainder, 0, sc_blockSize - size_remainder);
((uint8_t*)buf2)[sc_blockSize - 1] = size_remainder;
memcpy(buf3, blocks3 + nblocks * sc_blockSize, size_remainder);
memset(((uint8_t*)buf3) + size_remainder, 0, sc_blockSize - size_remainder);
((uint8_t*)buf3)[sc_blockSize - 1] = size_remainder;
__asm__ __volatile__ (
/* Load seed0 into XMM registers */
"movq %[seed0], %%rax\n\t"
"vmovq (%%rax), %%xmm9\n\t"
"movq %[seed1], %%rax\n\t"
"vmovhps (%%rax), %%xmm9, %%xmm9\n\t"
"movq %[seed2], %%rax\n\t"
"vmovq (%%rax), %%xmm13\n\t"
"movq %[seed3], %%rax\n\t"
"vmovhps (%%rax), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm9, %%ymm9\n\t"
"movq %[seed0], %%rax\n\t"
"vmovq 8(%%rax), %%xmm10\n\t"
"movq %[seed1], %%rax\n\t"
"vmovhps 8(%%rax), %%xmm10, %%xmm10\n\t"
"movq %[seed2], %%rax\n\t"
"vmovq 8(%%rax), %%xmm13\n\t"
"movq %[seed3], %%rax\n\t"
"vmovhps 8(%%rax), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm10, %%ymm10\n\t"
/* Load sc_const into XMM15 and duplicate it across YMM15 */
"vmovq %[sc_const_val], %%xmm15\n\t"
"vpunpcklqdq %%xmm15, %%xmm15, %%xmm15\n\t"
"vinserti128 $1, %%xmm15, %%ymm15, %%ymm15\n\t"
/* Initialize h0..h11 */
"vmovdqa %%ymm9, %%ymm0\n\t"
"vmovdqa %%ymm9, %%ymm3\n\t"
"vmovdqa %%ymm9, %%ymm6\n\t"
"vmovdqa %%ymm10, %%ymm1\n\t"
"vmovdqa %%ymm10, %%ymm4\n\t"
"vmovdqa %%ymm10, %%ymm7\n\t"
"vmovdqa %%ymm15, %%ymm2\n\t"
"vmovdqa %%ymm15, %%ymm5\n\t"
"vmovdqa %%ymm15, %%ymm8\n\t"
"vmovdqa %%ymm15, %%ymm11\n\t"
/* Main loop */
"1:\n\t"
"cmp %[end0], %[blocks0]\n\t"
"jae 2f\n\t"
ASM_MIX_AVX2
"add $96, %[blocks0]\n\t"
"add $96, %[blocks1]\n\t"
"add $96, %[blocks2]\n\t"
"add $96, %[blocks3]\n\t"
"jmp 1b\n\t"
"2:\n\t"
/* Copy buf0..buf3 pointers into blocks0..blocks3 to reuse registers */
"leaq %[buf0], %[blocks0]\n\t"
"leaq %[buf1], %[blocks1]\n\t"
"leaq %[buf2], %[blocks2]\n\t"
"leaq %[buf3], %[blocks3]\n\t"
/* Load and add buf0..buf3 elements */
"vmovq 0*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 0*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 0*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 0*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm0, %%ymm0\n\t"
"vmovq 1*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 1*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 1*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 1*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm1, %%ymm1\n\t"
"vmovq 2*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 2*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 2*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 2*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm2, %%ymm2\n\t"
"vmovq 3*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 3*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 3*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 3*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm3, %%ymm3\n\t"
"vmovq 4*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 4*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 4*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 4*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm4, %%ymm4\n\t"
"vmovq 5*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 5*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 5*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 5*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm5, %%ymm5\n\t"
"vmovq 6*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 6*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 6*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 6*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm6, %%ymm6\n\t"
"vmovq 7*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 7*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 7*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 7*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm7, %%ymm7\n\t"
"vmovq 8*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 8*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 8*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 8*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm8, %%ymm8\n\t"
"vmovq 9*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 9*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 9*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 9*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm9, %%ymm9\n\t"
"vmovq 10*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 10*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 10*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 10*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm10, %%ymm10\n\t"
"vmovq 11*8(%[blocks0]), %%xmm12\n\t"
"vmovhps 11*8(%[blocks1]), %%xmm12, %%xmm12\n\t"
"vmovq 11*8(%[blocks2]), %%xmm13\n\t"
"vmovhps 11*8(%[blocks3]), %%xmm13, %%xmm13\n\t"
"vinserti128 $1, %%xmm13, %%ymm12, %%ymm12\n\t"
"vpaddq %%ymm12, %%ymm11, %%ymm11\n\t"
/* EndPartial 3 times */
ASM_END_PARTIAL_AVX2
ASM_END_PARTIAL_AVX2
ASM_END_PARTIAL_AVX2
/* Extract upper halves of h0 and h1 */
"vextracti128 $1, %%ymm0, %%xmm12\n\t"
"vextracti128 $1, %%ymm1, %%xmm13\n\t"
/* Store digest0 and digest1 using XMM registers */
"movq %[digest0], %%rax\n\t"
"vmovq %%xmm0, (%%rax)\n\t"
"vmovq %%xmm1, 8(%%rax)\n\t"
"movq %[digest1], %%rcx\n\t"
"vmovhps %%xmm0, (%%rcx)\n\t"
"vmovhps %%xmm1, 8(%%rcx)\n\t"
/* Store digest2 and digest3 using extracted XMM registers */
"movq %[digest2], %%rdx\n\t"
"vmovq %%xmm12, (%%rdx)\n\t"
"vmovq %%xmm13, 8(%%rdx)\n\t"
"movq %[digest3], %%r8\n\t"
"vmovhps %%xmm12, (%%r8)\n\t"
"vmovhps %%xmm13, 8(%%r8)\n\t"
: [blocks0] "+r" (blocks0),
[blocks1] "+r" (blocks1),
[blocks2] "+r" (blocks2),
[blocks3] "+r" (blocks3)
: [end0] "r" (end0),
[seed0] "m" (seed0),
[seed1] "m" (seed1),
[seed2] "m" (seed2),
[seed3] "m" (seed3),
[digest0] "m" (digest0),
[digest1] "m" (digest1),
[digest2] "m" (digest2),
[digest3] "m" (digest3),
[sc_const_val] "m" (sc_const_val),
[buf0] "m" (buf0),
[buf1] "m" (buf1),
[buf2] "m" (buf2),
[buf3] "m" (buf3)
: "rax", "rcx", "rdx", "r8", "r9", "r10", "r11",
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "cc", "memory"
);
}
#else /* !__x86_64__ */
void SpookyHash128AVX(
const void* data0, const void* data1, const void* data2, const void* data3,
size_t size,
const uint8_t* seed0, const uint8_t* seed1, const uint8_t* seed2, const uint8_t* seed3,
uint8_t* digest0, uint8_t* digest1, uint8_t* digest2, uint8_t* digest3
)
{
SpookyHash128(data0, size, seed0, digest0);
SpookyHash128(data1, size, seed1, digest1);
SpookyHash128(data2, size, seed2, digest2);
SpookyHash128(data3, size, seed3, digest3);
}
#endif /* __x86_64__ */

323
cmdline/spooky2sse.c Normal file
View file

@ -0,0 +1,323 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2013 Andrea Mazzoleni
#if defined(__x86_64__)
#ifndef sc_numVars
#define sc_numVars 12
#endif
#ifndef sc_blockSize
#define sc_blockSize (sc_numVars * 8)
#endif
#ifndef sc_const
#define sc_const 0xdeadbeefdeadbeefLL
#endif
#define ASM_END_STEP(s1, s11, s2, r, r_diff) \
"paddq " s1 ", " s11 "\n\t" \
"pxor " s11 ", " s2 "\n\t" \
"movdqa " s1 ", %%xmm13\n\t" \
"psllq $" #r ", " s1 "\n\t" \
"psrlq $" #r_diff ", %%xmm13\n\t" \
"por %%xmm13, " s1 "\n\t"
#define ASM_END_PARTIAL \
ASM_END_STEP("%%xmm1", "%%xmm11", "%%xmm2", 44, 20) \
ASM_END_STEP("%%xmm2", "%%xmm0", "%%xmm3", 15, 49) \
ASM_END_STEP("%%xmm3", "%%xmm1", "%%xmm4", 34, 30) \
ASM_END_STEP("%%xmm4", "%%xmm2", "%%xmm5", 21, 43) \
ASM_END_STEP("%%xmm5", "%%xmm3", "%%xmm6", 38, 26) \
ASM_END_STEP("%%xmm6", "%%xmm4", "%%xmm7", 33, 31) \
ASM_END_STEP("%%xmm7", "%%xmm5", "%%xmm8", 10, 54) \
ASM_END_STEP("%%xmm8", "%%xmm6", "%%xmm9", 13, 51) \
ASM_END_STEP("%%xmm9", "%%xmm7", "%%xmm10", 38, 26) \
ASM_END_STEP("%%xmm10", "%%xmm8", "%%xmm11", 53, 11) \
ASM_END_STEP("%%xmm11", "%%xmm9", "%%xmm0", 42, 22) \
ASM_END_STEP("%%xmm0", "%%xmm10", "%%xmm1", 54, 10)
void SpookyHash128SSE(
const void* data0, const void* data1,
size_t size,
const uint8_t* seed0, const uint8_t* seed1,
uint8_t* digest0, uint8_t* digest1
)
{
uint64_t buf0[sc_numVars];
uint64_t buf1[sc_numVars];
size_t nblocks;
const uint8_t* blocks0;
const uint8_t* blocks1;
const uint8_t* end0;
size_t size_remainder;
static const uint64_t sc_const_val = sc_const;
nblocks = size / sc_blockSize;
blocks0 = (const uint8_t*)data0;
blocks1 = (const uint8_t*)data1;
end0 = blocks0 + nblocks * sc_blockSize;
/* tail data is computed beforehand */
size_remainder = size - nblocks * sc_blockSize;
memcpy(buf0, blocks0 + nblocks * sc_blockSize, size_remainder);
memset(((uint8_t*)buf0) + size_remainder, 0, sc_blockSize - size_remainder);
((uint8_t*)buf0)[sc_blockSize - 1] = size_remainder;
memcpy(buf1, blocks1 + nblocks * sc_blockSize, size_remainder);
memset(((uint8_t*)buf1) + size_remainder, 0, sc_blockSize - size_remainder);
((uint8_t*)buf1)[sc_blockSize - 1] = size_remainder;
__asm__ __volatile__ (
/* Load seed0 into XMM registers */
"movq (%[seed0]), %%xmm9\n\t"
"movhps (%[seed1]), %%xmm9\n\t"
"movq 8(%[seed0]), %%xmm10\n\t"
"movhps 8(%[seed1]), %%xmm10\n\t"
/* Load sc_const into XMM15 and duplicate it */
"movq (%[sc_const_ptr]), %%xmm15\n\t"
"punpcklqdq %%xmm15, %%xmm15\n\t"
/* Initialize h0..h11 */
"movdqa %%xmm9, %%xmm0\n\t"
"movdqa %%xmm9, %%xmm3\n\t"
"movdqa %%xmm9, %%xmm6\n\t"
"movdqa %%xmm10, %%xmm1\n\t"
"movdqa %%xmm10, %%xmm4\n\t"
"movdqa %%xmm10, %%xmm7\n\t"
"movdqa %%xmm15, %%xmm2\n\t"
"movdqa %%xmm15, %%xmm5\n\t"
"movdqa %%xmm15, %%xmm8\n\t"
"movdqa %%xmm15, %%xmm11\n\t"
/* Main loop */
"1:\n\t"
"cmp %[end0], %[blocks0]\n\t"
"jae 2f\n\t"
/* Step 0 */
"movq 0*8(%[blocks0]), %%xmm12\n\t"
"movhps 0*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm0\n\t"
"pxor %%xmm10, %%xmm2\n\t"
"pxor %%xmm0, %%xmm11\n\t"
"movdqa %%xmm0, %%xmm13\n\t"
"psllq $11, %%xmm0\n\t"
"psrlq $53, %%xmm13\n\t"
"por %%xmm13, %%xmm0\n\t"
"paddq %%xmm1, %%xmm11\n\t"
/* Step 1 */
"movq 1*8(%[blocks0]), %%xmm12\n\t"
"movhps 1*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm1\n\t"
"pxor %%xmm11, %%xmm3\n\t"
"pxor %%xmm1, %%xmm0\n\t"
"movdqa %%xmm1, %%xmm13\n\t"
"psllq $32, %%xmm1\n\t"
"psrlq $32, %%xmm13\n\t"
"por %%xmm13, %%xmm1\n\t"
"paddq %%xmm2, %%xmm0\n\t"
/* Step 2 */
"movq 2*8(%[blocks0]), %%xmm12\n\t"
"movhps 2*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm2\n\t"
"pxor %%xmm0, %%xmm4\n\t"
"pxor %%xmm2, %%xmm1\n\t"
"movdqa %%xmm2, %%xmm13\n\t"
"psllq $43, %%xmm2\n\t"
"psrlq $21, %%xmm13\n\t"
"por %%xmm13, %%xmm2\n\t"
"paddq %%xmm3, %%xmm1\n\t"
/* Step 3 */
"movq 3*8(%[blocks0]), %%xmm12\n\t"
"movhps 3*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm3\n\t"
"pxor %%xmm1, %%xmm5\n\t"
"pxor %%xmm3, %%xmm2\n\t"
"movdqa %%xmm3, %%xmm13\n\t"
"psllq $31, %%xmm3\n\t"
"psrlq $33, %%xmm13\n\t"
"por %%xmm13, %%xmm3\n\t"
"paddq %%xmm4, %%xmm2\n\t"
/* Step 4 */
"movq 4*8(%[blocks0]), %%xmm12\n\t"
"movhps 4*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm4\n\t"
"pxor %%xmm2, %%xmm6\n\t"
"pxor %%xmm4, %%xmm3\n\t"
"movdqa %%xmm4, %%xmm13\n\t"
"psllq $17, %%xmm4\n\t"
"psrlq $47, %%xmm13\n\t"
"por %%xmm13, %%xmm4\n\t"
"paddq %%xmm5, %%xmm3\n\t"
/* Step 5 */
"movq 5*8(%[blocks0]), %%xmm12\n\t"
"movhps 5*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm5\n\t"
"pxor %%xmm3, %%xmm7\n\t"
"pxor %%xmm5, %%xmm4\n\t"
"movdqa %%xmm5, %%xmm13\n\t"
"psllq $28, %%xmm5\n\t"
"psrlq $36, %%xmm13\n\t"
"por %%xmm13, %%xmm5\n\t"
"paddq %%xmm6, %%xmm4\n\t"
/* Step 6 */
"movq 6*8(%[blocks0]), %%xmm12\n\t"
"movhps 6*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm6\n\t"
"pxor %%xmm4, %%xmm8\n\t"
"pxor %%xmm6, %%xmm5\n\t"
"movdqa %%xmm6, %%xmm13\n\t"
"psllq $39, %%xmm6\n\t"
"psrlq $25, %%xmm13\n\t"
"por %%xmm13, %%xmm6\n\t"
"paddq %%xmm7, %%xmm5\n\t"
/* Step 7 */
"movq 7*8(%[blocks0]), %%xmm12\n\t"
"movhps 7*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm7\n\t"
"pxor %%xmm5, %%xmm9\n\t"
"pxor %%xmm7, %%xmm6\n\t"
"movdqa %%xmm7, %%xmm13\n\t"
"psllq $57, %%xmm7\n\t"
"psrlq $7, %%xmm13\n\t"
"por %%xmm13, %%xmm7\n\t"
"paddq %%xmm8, %%xmm6\n\t"
/* Step 8 */
"movq 8*8(%[blocks0]), %%xmm12\n\t"
"movhps 8*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm8\n\t"
"pxor %%xmm6, %%xmm10\n\t"
"pxor %%xmm8, %%xmm7\n\t"
"movdqa %%xmm8, %%xmm13\n\t"
"psllq $55, %%xmm8\n\t"
"psrlq $9, %%xmm13\n\t"
"por %%xmm13, %%xmm8\n\t"
"paddq %%xmm9, %%xmm7\n\t"
/* Step 9 */
"movq 9*8(%[blocks0]), %%xmm12\n\t"
"movhps 9*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm9\n\t"
"pxor %%xmm7, %%xmm11\n\t"
"pxor %%xmm9, %%xmm8\n\t"
"movdqa %%xmm9, %%xmm13\n\t"
"psllq $54, %%xmm9\n\t"
"psrlq $10, %%xmm13\n\t"
"por %%xmm13, %%xmm9\n\t"
"paddq %%xmm10, %%xmm8\n\t"
/* Step 10 */
"movq 10*8(%[blocks0]), %%xmm12\n\t"
"movhps 10*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm10\n\t"
"pxor %%xmm8, %%xmm0\n\t"
"pxor %%xmm10, %%xmm9\n\t"
"movdqa %%xmm10, %%xmm13\n\t"
"psllq $22, %%xmm10\n\t"
"psrlq $42, %%xmm13\n\t"
"por %%xmm13, %%xmm10\n\t"
"paddq %%xmm11, %%xmm9\n\t"
/* Step 11 */
"movq 11*8(%[blocks0]), %%xmm12\n\t"
"movhps 11*8(%[blocks1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm11\n\t"
"pxor %%xmm9, %%xmm1\n\t"
"pxor %%xmm11, %%xmm10\n\t"
"movdqa %%xmm11, %%xmm13\n\t"
"psllq $46, %%xmm11\n\t"
"psrlq $18, %%xmm13\n\t"
"por %%xmm13, %%xmm11\n\t"
"paddq %%xmm0, %%xmm10\n\t"
"add $96, %[blocks0]\n\t"
"add $96, %[blocks1]\n\t"
"jmp 1b\n\t"
"2:\n\t"
/* Load and add buf0 and buf1 elements */
"movq 0*8(%[buf0]), %%xmm12\n\t"
"movhps 0*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm0\n\t"
"movq 1*8(%[buf0]), %%xmm12\n\t"
"movhps 1*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm1\n\t"
"movq 2*8(%[buf0]), %%xmm12\n\t"
"movhps 2*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm2\n\t"
"movq 3*8(%[buf0]), %%xmm12\n\t"
"movhps 3*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm3\n\t"
"movq 4*8(%[buf0]), %%xmm12\n\t"
"movhps 4*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm4\n\t"
"movq 5*8(%[buf0]), %%xmm12\n\t"
"movhps 5*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm5\n\t"
"movq 6*8(%[buf0]), %%xmm12\n\t"
"movhps 6*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm6\n\t"
"movq 7*8(%[buf0]), %%xmm12\n\t"
"movhps 7*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm7\n\t"
"movq 8*8(%[buf0]), %%xmm12\n\t"
"movhps 8*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm8\n\t"
"movq 9*8(%[buf0]), %%xmm12\n\t"
"movhps 9*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm9\n\t"
"movq 10*8(%[buf0]), %%xmm12\n\t"
"movhps 10*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm10\n\t"
"movq 11*8(%[buf0]), %%xmm12\n\t"
"movhps 11*8(%[buf1]), %%xmm12\n\t"
"paddq %%xmm12, %%xmm11\n\t"
/* EndPartial 3 times */
ASM_END_PARTIAL
ASM_END_PARTIAL
ASM_END_PARTIAL
/* Store back h0 and h1 to output digests */
"movq %%xmm0, (%[digest0])\n\t"
"movhps %%xmm0, (%[digest1])\n\t"
"movq %%xmm1, 8(%[digest0])\n\t"
"movhps %%xmm1, 8(%[digest1])\n\t"
: [blocks0] "+r" (blocks0),
[blocks1] "+r" (blocks1)
: [end0] "r" (end0),
[seed0] "r" (seed0),
[seed1] "r" (seed1),
[digest0] "r" (digest0),
[digest1] "r" (digest1),
[sc_const_ptr] "r" (&sc_const_val),
[buf0] "r" (buf0),
[buf1] "r" (buf1)
: "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "cc", "memory"
);
}
#endif /* __x86_64__ */

View file

@ -760,8 +760,12 @@ unsigned membesthash(void)
#include "murmur3.c"
#include "spooky2.c"
#include "spooky2sse.c"
#include "spooky2avx.c"
#include "metro.c"
#include "museair.c"
#include "museairsse.c"
#include "museairavx.c"
void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size)
{

View file

@ -230,6 +230,12 @@ const char* memhashname(unsigned kind);
* Compute the HASH of a memory block.
* Seed is a 128 bit vector.
*/
void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest);
void SpookyHash128SSE(const void* data0, const void* data1, size_t size, const uint8_t* seed0, const uint8_t* seed1, uint8_t* digest0, uint8_t* digest1);
void SpookyHash128AVX(const void* data0, const void* data1, const void* data2, const void* data3, size_t size, const uint8_t* seed0, const uint8_t* seed1, const uint8_t* seed2, const uint8_t* seed3, uint8_t* digest0, uint8_t* digest1, uint8_t* digest2, uint8_t* digest3);
void MuseAirLoongSSE(const void* data0, const void* data1, size_t size, const uint8_t* seed0, const uint8_t* seed1, uint8_t* digest0, uint8_t* digest1);
void MuseAirLoongAVX(const void* data0, const void* data1, const void* data2, const void* data3, size_t size, const uint8_t* seed0, const uint8_t* seed1, const uint8_t* seed2, const uint8_t* seed3, uint8_t* digest0, uint8_t* digest1, uint8_t* digest2, uint8_t* digest3);
void MuseAirLoong(const void* bytes, size_t len, const uint8_t* seed, uint8_t* out);
void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size);
/**