This commit is contained in:
Jay D Dee
2020-01-18 15:14:27 -05:00
parent 70089d1224
commit 1a7a573675
105 changed files with 3579 additions and 2833 deletions

View File

@@ -2,13 +2,6 @@
//#define TASM
#define TINTR
//#define AES_NI
//#ifdef AES_NI
// specify AES-NI, AVX (with AES-NI) or vector-permute implementation
//#ifndef NO_AES_NI
// Not to be confused with AVX512VAES
#define VAES
// #define VAVX

View File

@@ -14,7 +14,7 @@
#include "miner.h"
#include "simd-utils.h"
#ifndef NO_AES_NI
#ifdef __AES__
#include "groestl-version.h"
@@ -91,8 +91,9 @@ HashReturn_gr reinit_groestl( hashState_groestl* ctx )
ctx->chaining[i] = _mm_setzero_si128();
ctx->buffer[i] = _mm_setzero_si128();
}
((u64*)ctx->chaining)[COLS-1] = U64BIG((u64)LENGTH);
INIT(ctx->chaining);
ctx->chaining[ 6 ] = m128_const_64( 0x0200000000000000, 0 );
// ((u64*)ctx->chaining)[COLS-1] = U64BIG((u64)LENGTH);
// INIT(ctx->chaining);
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
@@ -184,6 +185,82 @@ HashReturn_gr final_groestl( hashState_groestl* ctx, void* output )
return SUCCESS_GR;
}
int groestl512_full( hashState_groestl* ctx, void* output,
const void* input, uint64_t databitlen )
{
int i;
ctx->hashlen = 64;
SET_CONSTANTS();
for ( i = 0; i < SIZE512; i++ )
{
ctx->chaining[i] = _mm_setzero_si128();
ctx->buffer[i] = _mm_setzero_si128();
}
ctx->chaining[ 6 ] = m128_const_64( 0x0200000000000000, 0 );
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
const int len = (int)databitlen / 128;
const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i
const int hash_offset = SIZE512 - hashlen_m128i;
int rem = ctx->rem_ptr;
uint64_t blocks = len / SIZE512;
__m128i* in = (__m128i*)input;
// --- update ---
// digest any full blocks, process directly from input
for ( i = 0; i < blocks; i++ )
TF1024( ctx->chaining, &in[ i * SIZE512 ] );
ctx->buf_ptr = blocks * SIZE512;
// copy any remaining data to buffer, it may already contain data
// from a previous update for a midstate precalc
for ( i = 0; i < len % SIZE512; i++ )
ctx->buffer[ rem + i ] = in[ ctx->buf_ptr + i ];
i += rem; // use i as rem_ptr in final
//--- final ---
blocks++; // adjust for final block
if ( i == len -1 )
{
// only 128 bits left in buffer, all padding at once
ctx->buffer[i] = _mm_set_epi8( blocks,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0x80 );
}
else
{
// add first padding
ctx->buffer[i] = _mm_set_epi8( 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0x80 );
// add zero padding
for ( i += 1; i < SIZE512 - 1; i++ )
ctx->buffer[i] = _mm_setzero_si128();
// add length padding, second last byte is zero unless blocks > 255
ctx->buffer[i] = _mm_set_epi8( blocks, blocks>>8, 0,0, 0,0,0,0,
0, 0 ,0,0, 0,0,0,0 );
}
// digest final padding block and do output transform
TF1024( ctx->chaining, ctx->buffer );
OF1024( ctx->chaining );
// store hash result in output
for ( i = 0; i < hashlen_m128i; i++ )
casti_m128i( output, i ) = ctx->chaining[ hash_offset + i ];
return 0;
}
HashReturn_gr update_and_final_groestl( hashState_groestl* ctx, void* output,
const void* input, DataLength_gr databitlen )
{

View File

@@ -87,5 +87,6 @@ HashReturn_gr final_groestl( hashState_groestl*, void* );
HashReturn_gr update_and_final_groestl( hashState_groestl*, void*,
const void*, DataLength_gr );
int groestl512_full( hashState_groestl*, void*, const void*, uint64_t );
#endif /* __hash_h */

View File

@@ -11,7 +11,7 @@
#include "miner.h"
#include "simd-utils.h"
#ifndef NO_AES_NI
#ifdef __AES__
#include "groestl-version.h"
@@ -86,8 +86,11 @@ HashReturn_gr reinit_groestl256(hashState_groestl256* ctx)
ctx->chaining[i] = _mm_setzero_si128();
ctx->buffer[i] = _mm_setzero_si128();
}
((u64*)ctx->chaining)[COLS-1] = U64BIG((u64)LENGTH);
INIT256(ctx->chaining);
ctx->chaining[ 3 ] = m128_const_64( 0, 0x0100000000000000 );
// ((u64*)ctx->chaining)[COLS-1] = U64BIG((u64)LENGTH);
// INIT256(ctx->chaining);
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;

View File

@@ -93,9 +93,6 @@ typedef enum
typedef struct {
__attribute__ ((aligned (32))) __m128i chaining[SIZE256];
__attribute__ ((aligned (32))) __m128i buffer[SIZE256];
// __attribute__ ((aligned (32))) u64 chaining[SIZE/8]; /* actual state */
// __attribute__ ((aligned (32))) BitSequence_gr buffer[SIZE]; /* data buffer */
// u64 block_counter; /* message block counter */
int hashlen; // bytes
int blk_count;
int buf_ptr; /* data buffer pointer */

View File

@@ -49,7 +49,7 @@ int scanhash_groestl_4way( struct work *work, uint32_t max_nonce,
pdata[19] = n;
for ( int lane = 0; lane < 4; lane++ )
if ( ( hash+(lane<<3) )[7] < Htarg )
if ( ( hash+(lane<<3) )[7] <= Htarg )
if ( fulltest( hash+(lane<<3), ptarget) && !opt_benchmark )
{
pdata[19] = n + lane;

View File

@@ -3,19 +3,18 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifdef NO_AES_NI
#include "sph_groestl.h"
#else
#ifdef __AES__
#include "algo/groestl/aes_ni/hash-groestl.h"
#else
#include "sph_groestl.h"
#endif
typedef struct
{
#ifdef NO_AES_NI
sph_groestl512_context groestl1, groestl2;
#else
#ifdef __AES__
hashState_groestl groestl1, groestl2;
#else
sph_groestl512_context groestl1, groestl2;
#endif
} groestl_ctx_holder;
@@ -24,12 +23,12 @@ static groestl_ctx_holder groestl_ctx;
void init_groestl_ctx()
{
#ifdef NO_AES_NI
sph_groestl512_init( &groestl_ctx.groestl1 );
sph_groestl512_init( &groestl_ctx.groestl2 );
#else
#ifdef __AES__
init_groestl( &groestl_ctx.groestl1, 64 );
init_groestl( &groestl_ctx.groestl2, 64 );
#else
sph_groestl512_init( &groestl_ctx.groestl1 );
sph_groestl512_init( &groestl_ctx.groestl2 );
#endif
}
@@ -39,18 +38,18 @@ void groestlhash( void *output, const void *input )
groestl_ctx_holder ctx __attribute__ ((aligned (64)));
memcpy( &ctx, &groestl_ctx, sizeof(groestl_ctx) );
#ifdef NO_AES_NI
sph_groestl512(&ctx.groestl1, input, 80);
sph_groestl512_close(&ctx.groestl1, hash);
sph_groestl512(&ctx.groestl2, hash, 64);
sph_groestl512_close(&ctx.groestl2, hash);
#else
#ifdef __AES__
update_and_final_groestl( &ctx.groestl1, (char*)hash,
(const char*)input, 640 );
update_and_final_groestl( &ctx.groestl2, (char*)hash,
(const char*)hash, 512 );
#else
sph_groestl512(&ctx.groestl1, input, 80);
sph_groestl512_close(&ctx.groestl1, hash);
sph_groestl512(&ctx.groestl2, hash, 64);
sph_groestl512_close(&ctx.groestl2, hash);
#endif
memcpy(output, hash, 32);
}

View File

@@ -1,4 +1,5 @@
/* hash.c Aug 2011
* groestl512-hash-4way https://github.com/JayDDee/cpuminer-opt 2019-12.
*
* Groestl implementation for different versions.
* Author: Krystian Matusiewicz, Günther A. Roland, Martin Schläffer
@@ -6,51 +7,18 @@
* This code is placed in the public domain
*/
// Optimized for hash and data length that are integrals of __m128i
#include <memory.h>
#include "hash-groestl256.h"
#include "groestl256-intr-4way.h"
#include "miner.h"
#include "simd-utils.h"
#ifndef NO_AES_NI
#if defined(__VAES__) && defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__)
#include "groestl-version.h"
#ifdef TASM
#ifdef VAES
#include "groestl256-asm-aes.h"
#else
#ifdef VAVX
#include "groestl256-asm-avx.h"
#else
#ifdef VVPERM
#include "groestl256-asm-vperm.h"
#else
#error NO VERSION SPECIFIED (-DV[AES/AVX/VVPERM])
#endif
#endif
#endif
#else
#ifdef TINTR
#ifdef VAES
#include "groestl256-intr-aes.h"
#else
#ifdef VAVX
#include "groestl256-intr-avx.h"
#else
#ifdef VVPERM
#include "groestl256-intr-vperm.h"
#else
#error NO VERSION SPECIFIED (-DV[AES/AVX/VVPERM])
#endif
#endif
#endif
#else
#error NO TYPE SPECIFIED (-DT[ASM/INTR])
#endif
#endif
/* initialise context */
HashReturn_gr init_groestl256( hashState_groestl256* ctx, int hashlen )
int groestl256_4way_init( groestl256_4way_context* ctx, uint64_t hashlen )
{
int i;
@@ -58,223 +26,84 @@ HashReturn_gr init_groestl256( hashState_groestl256* ctx, int hashlen )
SET_CONSTANTS();
if (ctx->chaining == NULL || ctx->buffer == NULL)
return FAIL_GR;
return 1;
for ( i = 0; i < SIZE256; i++ )
{
ctx->chaining[i] = _mm_setzero_si128();
ctx->buffer[i] = _mm_setzero_si128();
ctx->chaining[i] = m512_zero;
ctx->buffer[i] = m512_zero;
}
((u64*)ctx->chaining)[COLS-1] = U64BIG((u64)LENGTH);
INIT256( ctx->chaining );
// The only non-zero in the IV is len. It can be hard coded.
ctx->chaining[ 3 ] = m512_const2_64( 0, 0x0100000000000000 );
// uint64_t len = U64BIG((uint64_t)LENGTH);
// ctx->chaining[ COLS/2 -1 ] = _mm512_set4_epi64( len, 0, len, 0 );
// INIT256_4way(ctx->chaining);
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
return SUCCESS_GR;
return 0;
}
HashReturn_gr reinit_groestl256(hashState_groestl256* ctx)
{
int i;
if (ctx->chaining == NULL || ctx->buffer == NULL)
return FAIL_GR;
for ( i = 0; i < SIZE256; i++ )
{
ctx->chaining[i] = _mm_setzero_si128();
ctx->buffer[i] = _mm_setzero_si128();
}
((u64*)ctx->chaining)[COLS-1] = U64BIG((u64)LENGTH);
INIT256(ctx->chaining);
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
return SUCCESS_GR;
}
// Use this only for midstate and never for cryptonight
HashReturn_gr update_groestl256( hashState_groestl256* ctx, const void* input,
DataLength_gr databitlen )
{
__m128i* in = (__m128i*)input;
const int len = (int)databitlen / 128; // bits to __m128i
const int blocks = len / SIZE256; // __M128i to blocks
int rem = ctx->rem_ptr;
int i;
ctx->blk_count = blocks;
ctx->databitlen = databitlen;
// digest any full blocks
for ( i = 0; i < blocks; i++ )
TF512( ctx->chaining, &in[ i * SIZE256 ] );
// adjust buf_ptr to last block
ctx->buf_ptr = blocks * SIZE256;
// Copy any remainder to buffer
for ( i = 0; i < len % SIZE256; i++ )
ctx->buffer[ rem + i ] = in[ ctx->buf_ptr + i ];
// adjust rem_ptr for new data
ctx->rem_ptr += i;
return SUCCESS_GR;
}
// don't use this at all
HashReturn_gr final_groestl256( hashState_groestl256* ctx, void* output )
{
const int len = (int)ctx->databitlen / 128; // bits to __m128i
const int blocks = ctx->blk_count + 1; // adjust for final block
const int rem_ptr = ctx->rem_ptr; // end of data start of padding
const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i
const int hash_offset = SIZE256 - hashlen_m128i; // where in buffer
int i;
// first pad byte = 0x80, last pad byte = block count
// everything in between is zero
if ( rem_ptr == len - 1 )
{
// all padding at once
ctx->buffer[rem_ptr] = _mm_set_epi8( blocks,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0x80 );
}
else
{
// add first padding
ctx->buffer[rem_ptr] = _mm_set_epi8( 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0x80 );
// add zero padding
for ( i = rem_ptr + 1; i < SIZE256 - 1; i++ )
ctx->buffer[i] = _mm_setzero_si128();
// add length padding
// cheat since we know the block count is trivial, good if block < 256
ctx->buffer[i] = _mm_set_epi8( blocks,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0 );
}
// digest final padding block and do output transform
TF512( ctx->chaining, ctx->buffer );
OF512( ctx->chaining );
// store hash result in output
for ( i = 0; i < hashlen_m128i; i++ )
casti_m128i( output, i ) = ctx->chaining[ hash_offset + i];
return SUCCESS_GR;
}
HashReturn_gr update_and_final_groestl256( hashState_groestl256* ctx,
void* output, const void* input, DataLength_gr databitlen )
int groestl256_4way_update_close( groestl256_4way_context* ctx, void* output,
const void* input, uint64_t databitlen )
{
const int len = (int)databitlen / 128;
const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i
const int hash_offset = SIZE256 - hashlen_m128i;
int rem = ctx->rem_ptr;
int blocks = len / SIZE256;
__m128i* in = (__m128i*)input;
__m512i* in = (__m512i*)input;
int i;
// --- update ---
// digest any full blocks, process directly from input
for ( i = 0; i < blocks; i++ )
TF512( ctx->chaining, &in[ i * SIZE256 ] );
TF512_4way( ctx->chaining, &in[ i * SIZE256 ] );
ctx->buf_ptr = blocks * SIZE256;
// cryptonight has 200 byte input, an odd number of __m128i
// remainder is only 8 bytes, ie u64.
if ( databitlen % 128 !=0 )
{
// must be cryptonight, copy 64 bits of data
*(uint64_t*)(ctx->buffer) = *(uint64_t*)(&in[ ctx->buf_ptr ] );
i = -1; // signal for odd length
}
else
{
// Copy any remaining data to buffer for final transform
for ( i = 0; i < len % SIZE256; i++ )
ctx->buffer[ rem + i ] = in[ ctx->buf_ptr + i ];
i += rem; // use i as rem_ptr in final
}
// copy any remaining data to buffer, it may already contain data
// from a previous update for a midstate precalc
for ( i = 0; i < len % SIZE256; i++ )
ctx->buffer[ rem + i ] = in[ ctx->buf_ptr + i ];
i += rem; // use i as rem_ptr in final
//--- final ---
// adjust for final block
blocks++;
blocks++; // adjust for final block
if ( i == len - 1 )
{
// all padding at once
ctx->buffer[i] = _mm_set_epi8( blocks,blocks>>8,0,0, 0,0,0,0,
0, 0,0,0, 0,0,0,0x80 );
}
if ( i == SIZE256 - 1 )
{
// only 1 vector left in buffer, all padding at once
ctx->buffer[i] = m512_const1_128( _mm_set_epi8(
blocks, blocks>>8,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0x80 ) );
}
else
{
if ( i == -1 )
{
// cryptonight odd length
((uint64_t*)ctx->buffer)[ 1 ] = 0x80ull;
// finish the block with zero and length padding as normal
i = 0;
}
else
{
// add first padding
ctx->buffer[i] = _mm_set_epi8( 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0x80 );
}
// add first padding
ctx->buffer[i] = m512_const4_64( 0, 0x80, 0, 0x80 );
// add zero padding
for ( i += 1; i < SIZE256 - 1; i++ )
ctx->buffer[i] = _mm_setzero_si128();
// add length padding
// cheat since we know the block count is trivial, good if block < 256
ctx->buffer[i] = _mm_set_epi8( blocks,blocks>>8,0,0, 0,0,0,0,
0, 0,0,0, 0,0,0,0 );
ctx->buffer[i] = m512_zero;
// add length padding, second last byte is zero unless blocks > 255
ctx->buffer[i] = m512_const1_128( _mm_set_epi8(
blocks, blocks>>8, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 ) );
}
// digest final padding block and do output transform
TF512( ctx->chaining, ctx->buffer );
OF512( ctx->chaining );
// digest final padding block and do output transform
TF512_4way( ctx->chaining, ctx->buffer );
OF512_4way( ctx->chaining );
// store hash result in output
for ( i = 0; i < hashlen_m128i; i++ )
casti_m128i( output, i ) = ctx->chaining[ hash_offset + i ];
casti_m512i( output, i ) = ctx->chaining[ hash_offset + i ];
return SUCCESS_GR;
return 0;
}
/* hash bit sequence */
HashReturn_gr hash_groestl256(int hashbitlen,
const BitSequence_gr* data,
DataLength_gr databitlen,
BitSequence_gr* hashval) {
HashReturn_gr ret;
hashState_groestl256 context;
#endif // VAES
/* initialise */
if ((ret = init_groestl256(&context, hashbitlen/8)) != SUCCESS_GR)
return ret;
/* process message */
if ((ret = update_groestl256(&context, data, databitlen)) != SUCCESS_GR)
return ret;
/* finalise */
ret = final_groestl256(&context, hashval);
return ret;
}
/* eBash API */
//#ifdef crypto_hash_BYTES
//int crypto_hash(unsigned char *out, const unsigned char *in, unsigned long long inlen)
//{
// if (hash_groestl(crypto_hash_BYTES * 8, in, inlen * 8,out) == SUCCESS_GR) return 0;
// return -1;
//}
//#endif
#endif

View File

@@ -6,56 +6,39 @@
* This code is placed in the public domain
*/
#ifndef __hash_h
#define __hash_h
#if !defined(GROESTL256_HASH_4WAY_H__)
#define GROESTL256_HASH_4WAY_H__ 1
#include "simd-utils.h"
#include <immintrin.h>
#include <stdint.h>
#include <stdio.h>
#if defined(_WIN64) || defined(__WINDOWS__)
#include <windows.h>
#endif
#include <stdlib.h>
/* eBash API begin */
/*
#include "crypto_hash.h"
#ifdef crypto_hash_BYTES
#include <crypto_uint8.h>
#include <crypto_uint32.h>
#include <crypto_uint64.h>
typedef crypto_uint8 u8;
typedef crypto_uint32 u32;
typedef crypto_uint64 u64;
#endif
*/
/* eBash API end */
//#define LENGTH (512)
#include "brg_endian.h"
#define NEED_UINT_64T
#include "algo/sha/brg_types.h"
#ifdef IACA_TRACE
#include IACA_MARKS
#endif
#if defined(__VAES__) && defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__)
#define LENGTH (256)
//#include "brg_endian.h"
//#define NEED_UINT_64T
//#include "algo/sha/brg_types.h"
/* some sizes (number of bytes) */
#define ROWS (8)
#define LENGTHFIELDLEN (ROWS)
#define COLS512 (8)
//#define COLS1024 (16)
#define SIZE_512 ((ROWS)*(COLS512))
//#define SIZE1024 ((ROWS)*(COLS1024))
//#define SIZE_1024 ((ROWS)*(COLS1024))
#define ROUNDS512 (10)
//#define ROUNDS1024 (14)
//#if LENGTH<=256
#define COLS (COLS512)
//#define SIZE (SIZE512)
#define SIZE (SIZE512)
#define ROUNDS (ROUNDS512)
//#else
//#define COLS (COLS1024)
@@ -63,59 +46,30 @@ typedef crypto_uint64 u64;
//#define ROUNDS (ROUNDS1024)
//#endif
#define ROTL64(a,n) ((((a)<<(n))|((a)>>(64-(n))))&li_64(ffffffffffffffff))
#if (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN)
#define EXT_BYTE(var,n) ((u8)((u64)(var) >> (8*(7-(n)))))
#define U64BIG(a) (a)
#endif /* IS_BIG_ENDIAN */
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
#define EXT_BYTE(var,n) ((u8)((u64)(var) >> (8*n)))
#define U64BIG(a) \
((ROTL64(a, 8) & li_64(000000FF000000FF)) | \
(ROTL64(a,24) & li_64(0000FF000000FF00)) | \
(ROTL64(a,40) & li_64(00FF000000FF0000)) | \
(ROTL64(a,56) & li_64(FF000000FF000000)))
#endif /* IS_LITTLE_ENDIAN */
typedef unsigned char BitSequence_gr;
typedef unsigned long long DataLength_gr;
typedef enum
{
SUCCESS_GR = 0,
FAIL_GR = 1,
BAD_HASHBITLEN_GR = 2
} HashReturn_gr;
#define SIZE256 (SIZE_512/16)
typedef struct {
__attribute__ ((aligned (32))) __m128i chaining[SIZE256];
__attribute__ ((aligned (32))) __m128i buffer[SIZE256];
// __attribute__ ((aligned (32))) u64 chaining[SIZE/8]; /* actual state */
// __attribute__ ((aligned (32))) BitSequence_gr buffer[SIZE]; /* data buffer */
// u64 block_counter; /* message block counter */
int hashlen; // bytes
int blk_count;
int buf_ptr; /* data buffer pointer */
__attribute__ ((aligned (128))) __m512i chaining[SIZE256];
__attribute__ ((aligned (64))) __m512i buffer[SIZE256];
int hashlen; // byte
int blk_count; // SIZE_m128i
int buf_ptr; // __m128i offset
int rem_ptr;
int databitlen;
} hashState_groestl256;
int databitlen; // bits
} groestl256_4way_context;
HashReturn_gr init_groestl256( hashState_groestl256*, int );
HashReturn_gr reinit_groestl256( hashState_groestl256* );
int groestl256_4way_init( groestl256_4way_context*, uint64_t );
HashReturn_gr update_groestl256( hashState_groestl256*, const void*,
DataLength_gr );
//int reinit_groestl( hashState_groestl* );
HashReturn_gr final_groestl256( hashState_groestl256*, void* );
//int groestl512_4way_update( groestl256_4way_context*, const void*,
// uint64_t );
HashReturn_gr hash_groestli256( int, const BitSequence_gr*, DataLength_gr,
BitSequence_gr* );
//int groestl512_4way_close( groestl512_4way_context*, void* );
HashReturn_gr update_and_final_groestl256( hashState_groestl256*, void*,
const void*, DataLength_gr );
int groestl256_4way_update_close( groestl256_4way_context*, void*,
const void*, uint64_t );
#endif /* __hash_h */
#endif
#endif

View File

@@ -7,35 +7,37 @@
* This code is placed in the public domain
*/
#include <smmintrin.h>
#include <wmmintrin.h>
#include "hash-groestl256.h"
#if !defined(GROESTL256_INTR_4WAY_H__)
#define GROESTL256_INTR_4WAY_H__ 1
#include "groestl256-hash-4way.h"
#if defined(__VAES__)
/* global constants */
__m128i ROUND_CONST_Lx;
__m128i ROUND_CONST_L0[ROUNDS512];
__m128i ROUND_CONST_L7[ROUNDS512];
//__m128i ROUND_CONST_P[ROUNDS1024];
//__m128i ROUND_CONST_Q[ROUNDS1024];
__m128i TRANSP_MASK;
__m128i SUBSH_MASK[8];
__m128i ALL_1B;
__m128i ALL_FF;
__m512i ROUND_CONST_Lx;
__m512i ROUND_CONST_L0[ROUNDS512];
__m512i ROUND_CONST_L7[ROUNDS512];
//__m512i ROUND_CONST_P[ROUNDS1024];
//__m512i ROUND_CONST_Q[ROUNDS1024];
__m512i TRANSP_MASK;
__m512i SUBSH_MASK[8];
__m512i ALL_1B;
__m512i ALL_FF;
#define tos(a) #a
#define tostr(a) tos(a)
/* xmm[i] will be multiplied by 2
* xmm[j] will be lost
* xmm[k] has to be all 0x1b */
#define MUL2(i, j, k){\
j = _mm_xor_si128(j, j);\
j = _mm_cmpgt_epi8(j, i);\
i = _mm_add_epi8(i, i);\
j = _mm_and_si128(j, k);\
i = _mm_xor_si128(i, j);\
j = _mm512_xor_si512(j, j);\
j = _mm512_movm_epi8( _mm512_cmpgt_epi8_mask(j, i) );\
i = _mm512_add_epi8(i, i);\
j = _mm512_and_si512(j, k);\
i = _mm512_xor_si512(i, j);\
}
/**/
@@ -61,152 +63,188 @@ __m128i ALL_FF;
/* t_i = a_i + a_{i+1} */\
b6 = a0;\
b7 = a1;\
a0 = _mm_xor_si128(a0, a1);\
a0 = _mm512_xor_si512(a0, a1);\
b0 = a2;\
a1 = _mm_xor_si128(a1, a2);\
a1 = _mm512_xor_si512(a1, a2);\
b1 = a3;\
a2 = _mm_xor_si128(a2, a3);\
a2 = _mm512_xor_si512(a2, a3);\
b2 = a4;\
a3 = _mm_xor_si128(a3, a4);\
a3 = _mm512_xor_si512(a3, a4);\
b3 = a5;\
a4 = _mm_xor_si128(a4, a5);\
a4 = _mm512_xor_si512(a4, a5);\
b4 = a6;\
a5 = _mm_xor_si128(a5, a6);\
a5 = _mm512_xor_si512(a5, a6);\
b5 = a7;\
a6 = _mm_xor_si128(a6, a7);\
a7 = _mm_xor_si128(a7, b6);\
a6 = _mm512_xor_si512(a6, a7);\
a7 = _mm512_xor_si512(a7, b6);\
\
/* build y4 y5 y6 ... in regs xmm8, xmm9, xmm10 by adding t_i*/\
b0 = _mm_xor_si128(b0, a4);\
b6 = _mm_xor_si128(b6, a4);\
b1 = _mm_xor_si128(b1, a5);\
b7 = _mm_xor_si128(b7, a5);\
b2 = _mm_xor_si128(b2, a6);\
b0 = _mm_xor_si128(b0, a6);\
b0 = _mm512_xor_si512(b0, a4);\
b6 = _mm512_xor_si512(b6, a4);\
b1 = _mm512_xor_si512(b1, a5);\
b7 = _mm512_xor_si512(b7, a5);\
b2 = _mm512_xor_si512(b2, a6);\
b0 = _mm512_xor_si512(b0, a6);\
/* spill values y_4, y_5 to memory */\
TEMP0 = b0;\
b3 = _mm_xor_si128(b3, a7);\
b1 = _mm_xor_si128(b1, a7);\
b3 = _mm512_xor_si512(b3, a7);\
b1 = _mm512_xor_si512(b1, a7);\
TEMP1 = b1;\
b4 = _mm_xor_si128(b4, a0);\
b2 = _mm_xor_si128(b2, a0);\
b4 = _mm512_xor_si512(b4, a0);\
b2 = _mm512_xor_si512(b2, a0);\
/* save values t0, t1, t2 to xmm8, xmm9 and memory */\
b0 = a0;\
b5 = _mm_xor_si128(b5, a1);\
b3 = _mm_xor_si128(b3, a1);\
b5 = _mm512_xor_si512(b5, a1);\
b3 = _mm512_xor_si512(b3, a1);\
b1 = a1;\
b6 = _mm_xor_si128(b6, a2);\
b4 = _mm_xor_si128(b4, a2);\
b6 = _mm512_xor_si512(b6, a2);\
b4 = _mm512_xor_si512(b4, a2);\
TEMP2 = a2;\
b7 = _mm_xor_si128(b7, a3);\
b5 = _mm_xor_si128(b5, a3);\
b7 = _mm512_xor_si512(b7, a3);\
b5 = _mm512_xor_si512(b5, a3);\
\
/* compute x_i = t_i + t_{i+3} */\
a0 = _mm_xor_si128(a0, a3);\
a1 = _mm_xor_si128(a1, a4);\
a2 = _mm_xor_si128(a2, a5);\
a3 = _mm_xor_si128(a3, a6);\
a4 = _mm_xor_si128(a4, a7);\
a5 = _mm_xor_si128(a5, b0);\
a6 = _mm_xor_si128(a6, b1);\
a7 = _mm_xor_si128(a7, TEMP2);\
a0 = _mm512_xor_si512(a0, a3);\
a1 = _mm512_xor_si512(a1, a4);\
a2 = _mm512_xor_si512(a2, a5);\
a3 = _mm512_xor_si512(a3, a6);\
a4 = _mm512_xor_si512(a4, a7);\
a5 = _mm512_xor_si512(a5, b0);\
a6 = _mm512_xor_si512(a6, b1);\
a7 = _mm512_xor_si512(a7, TEMP2);\
\
/* compute z_i : double x_i using temp xmm8 and 1B xmm9 */\
/* compute w_i : add y_{i+4} */\
b1 = ALL_1B;\
b1 = m512_const1_64( 0x1b1b1b1b1b1b1b1b );\
MUL2(a0, b0, b1);\
a0 = _mm_xor_si128(a0, TEMP0);\
a0 = _mm512_xor_si512(a0, TEMP0);\
MUL2(a1, b0, b1);\
a1 = _mm_xor_si128(a1, TEMP1);\
a1 = _mm512_xor_si512(a1, TEMP1);\
MUL2(a2, b0, b1);\
a2 = _mm_xor_si128(a2, b2);\
a2 = _mm512_xor_si512(a2, b2);\
MUL2(a3, b0, b1);\
a3 = _mm_xor_si128(a3, b3);\
a3 = _mm512_xor_si512(a3, b3);\
MUL2(a4, b0, b1);\
a4 = _mm_xor_si128(a4, b4);\
a4 = _mm512_xor_si512(a4, b4);\
MUL2(a5, b0, b1);\
a5 = _mm_xor_si128(a5, b5);\
a5 = _mm512_xor_si512(a5, b5);\
MUL2(a6, b0, b1);\
a6 = _mm_xor_si128(a6, b6);\
a6 = _mm512_xor_si512(a6, b6);\
MUL2(a7, b0, b1);\
a7 = _mm_xor_si128(a7, b7);\
a7 = _mm512_xor_si512(a7, b7);\
\
/* compute v_i : double w_i */\
/* add to y_4 y_5 .. v3, v4, ... */\
MUL2(a0, b0, b1);\
b5 = _mm_xor_si128(b5, a0);\
b5 = _mm512_xor_si512(b5, a0);\
MUL2(a1, b0, b1);\
b6 = _mm_xor_si128(b6, a1);\
b6 = _mm512_xor_si512(b6, a1);\
MUL2(a2, b0, b1);\
b7 = _mm_xor_si128(b7, a2);\
b7 = _mm512_xor_si512(b7, a2);\
MUL2(a5, b0, b1);\
b2 = _mm_xor_si128(b2, a5);\
b2 = _mm512_xor_si512(b2, a5);\
MUL2(a6, b0, b1);\
b3 = _mm_xor_si128(b3, a6);\
b3 = _mm512_xor_si512(b3, a6);\
MUL2(a7, b0, b1);\
b4 = _mm_xor_si128(b4, a7);\
b4 = _mm512_xor_si512(b4, a7);\
MUL2(a3, b0, b1);\
MUL2(a4, b0, b1);\
b0 = TEMP0;\
b1 = TEMP1;\
b0 = _mm_xor_si128(b0, a3);\
b1 = _mm_xor_si128(b1, a4);\
b0 = _mm512_xor_si512(b0, a3);\
b1 = _mm512_xor_si512(b1, a4);\
}/*MixBytes*/
#define SET_CONSTANTS(){\
ALL_1B = _mm_set_epi32(0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b);\
TRANSP_MASK = _mm_set_epi32(0x0f070b03, 0x0e060a02, 0x0d050901, 0x0c040800);\
SUBSH_MASK[0] = _mm_set_epi32(0x03060a0d, 0x08020509, 0x0c0f0104, 0x070b0e00);\
SUBSH_MASK[1] = _mm_set_epi32(0x04070c0f, 0x0a03060b, 0x0e090205, 0x000d0801);\
SUBSH_MASK[2] = _mm_set_epi32(0x05000e09, 0x0c04070d, 0x080b0306, 0x010f0a02);\
SUBSH_MASK[3] = _mm_set_epi32(0x0601080b, 0x0e05000f, 0x0a0d0407, 0x02090c03);\
SUBSH_MASK[4] = _mm_set_epi32(0x0702090c, 0x0f060108, 0x0b0e0500, 0x030a0d04);\
SUBSH_MASK[5] = _mm_set_epi32(0x00030b0e, 0x0907020a, 0x0d080601, 0x040c0f05);\
SUBSH_MASK[6] = _mm_set_epi32(0x01040d08, 0x0b00030c, 0x0f0a0702, 0x050e0906);\
SUBSH_MASK[7] = _mm_set_epi32(0x02050f0a, 0x0d01040e, 0x090c0003, 0x06080b07);\
for(i = 0; i < ROUNDS512; i++)\
{\
ROUND_CONST_L0[i] = _mm_set_epi32(0xffffffff, 0xffffffff, 0x70605040 ^ (i * 0x01010101), 0x30201000 ^ (i * 0x01010101));\
ROUND_CONST_L7[i] = _mm_set_epi32(0x8f9fafbf ^ (i * 0x01010101), 0xcfdfefff ^ (i * 0x01010101), 0x00000000, 0x00000000);\
}\
ROUND_CONST_Lx = _mm_set_epi32(0xffffffff, 0xffffffff, 0x00000000, 0x00000000);\
}while(0); \
// calculate the round constants seperately and load at startup
#define SET_CONSTANTS(){\
ALL_1B = _mm512_set1_epi32( 0x1b1b1b1b );\
TRANSP_MASK = _mm512_set_epi32( \
0x3f373b33, 0x3e363a32, 0x3d353931, 0x3c343830, \
0x2f272b23, 0x2e262a22, 0x2d252921, 0x2c242820, \
0x1f171b13, 0x1e161a12, 0x1d151911, 0x1c141810, \
0x0f070b03, 0x0e060a02, 0x0d050901, 0x0c040800 ); \
SUBSH_MASK[0] = _mm512_set_epi32( \
0x33363a3d, 0x38323539, 0x3c3f3134, 0x373b3e30, \
0x23262a2d, 0x28222529, 0x2c2f2124, 0x272b2e20, \
0x13161a1d, 0x18121519, 0x1c1f1114, 0x171b1e10, \
0x03060a0d, 0x08020509, 0x0c0f0104, 0x070b0e00 ); \
SUBSH_MASK[1] = _mm512_set_epi32( \
0x34373c3f, 0x3a33363b, 0x3e393235, 0x303d3831, \
0x24272c2f, 0x2a23262b, 0x2e292225, 0x202d2821, \
0x14171c1f, 0x1a13161b, 0x1e191215, 0x101d1801, \
0x04070c0f, 0x0a03060b, 0x0e090205, 0x000d0801 );\
SUBSH_MASK[2] = _mm512_set_epi32( \
0x35303e39, 0x3c34373d, 0x383b3336, 0x313f3a32, \
0x25202e29, 0x2c24272d, 0x282b2326, 0x212f2a22, \
0x15101e19, 0x1c14171d, 0x181b1316, 0x111f1a12, \
0x05000e09, 0x0c04070d, 0x080b0306, 0x010f0a02 );\
SUBSH_MASK[3] = _mm512_set_epi32( \
0x3631383b, 0x3e35303f, 0x3a3d3437, 0x32393c33, \
0x2621282b, 0x2e25202f, 0x2a2d2427, 0x22292c23, \
0x1611181b, 0x1e15101f, 0x1a1d1417, 0x12191c13, \
0x0601080b, 0x0e05000f, 0x0a0d0407, 0x02090c03 );\
SUBSH_MASK[4] = _mm512_set_epi32( \
0x3732393c, 0x3f363138, 0x3b3e3530, 0x333a3d34, \
0x2722292c, 0x2f262128, 0x2b2e2520, 0x232a2d24, \
0x1712191c, 0x1f161118, 0x1b1e1510, 0x131a1d14, \
0x0702090c, 0x0f060108, 0x0b0e0500, 0x030a0d04 );\
SUBSH_MASK[5] = _mm512_set_epi32( \
0x30333b3e, 0x3937323a, 0x3d383631, 0x343c3f35, \
0x20232b2e, 0x2927222a, 0x2d282621, 0x242c2f25, \
0x10131b1e, 0x1917121a, 0x1d181611, 0x141c1f15, \
0x00030b0e, 0x0907020a, 0x0d080601, 0x040c0f05 );\
SUBSH_MASK[6] = _mm512_set_epi32( \
0x31343d38, 0x3b30333c, 0x3f3a3732, 0x353e3936, \
0x21242d28, 0x2b20232c, 0x2f2a2722, 0x252e2926, \
0x11141d18, 0x1b10131c, 0x1f1a1712, 0x151e1916, \
0x01040d08, 0x0b00030c, 0x0f0a0702, 0x050e0906 );\
SUBSH_MASK[7] = _mm512_set_epi32( \
0x32353f3a, 0x3d31343e, 0x393c3033, 0x36383b37, \
0x22252f2a, 0x2d21242e, 0x292c2023, 0x26282b27, \
0x12151f1a, 0x1d11141e, 0x191c1013, 0x16181b17, \
0x02050f0a, 0x0d01040e, 0x090c0003, 0x06080b07 );\
for ( i = 0; i < ROUNDS512; i++ ) \
{\
ROUND_CONST_L0[i] = _mm512_set4_epi32( 0xffffffff, 0xffffffff, \
0x70605040 ^ ( i * 0x01010101 ), 0x30201000 ^ ( i * 0x01010101 ) ); \
ROUND_CONST_L7[i] = _mm512_set4_epi32( 0x8f9fafbf ^ ( i * 0x01010101 ), \
0xcfdfefff ^ ( i * 0x01010101 ), 0x00000000, 0x00000000 ); \
}\
ROUND_CONST_Lx = _mm512_set4_epi32( 0xffffffff, 0xffffffff, \
0x00000000, 0x00000000 ); \
}while(0);\
/* one round
* i = round number
* a0-a7 = input rows
* b0-b7 = output rows
*/
#define ROUND(i, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7){\
/* AddRoundConstant */\
b1 = ROUND_CONST_Lx;\
a0 = _mm_xor_si128(a0, (ROUND_CONST_L0[i]));\
a1 = _mm_xor_si128(a1, b1);\
a2 = _mm_xor_si128(a2, b1);\
a3 = _mm_xor_si128(a3, b1);\
a4 = _mm_xor_si128(a4, b1);\
a5 = _mm_xor_si128(a5, b1);\
a6 = _mm_xor_si128(a6, b1);\
a7 = _mm_xor_si128(a7, (ROUND_CONST_L7[i]));\
a0 = _mm512_xor_si512( a0, (ROUND_CONST_L0[i]) );\
a1 = _mm512_xor_si512( a1, b1 );\
a2 = _mm512_xor_si512( a2, b1 );\
a3 = _mm512_xor_si512( a3, b1 );\
a4 = _mm512_xor_si512( a4, b1 );\
a5 = _mm512_xor_si512( a5, b1 );\
a6 = _mm512_xor_si512( a6, b1 );\
a7 = _mm512_xor_si512( a7, (ROUND_CONST_L7[i]) );\
\
/* ShiftBytes + SubBytes (interleaved) */\
b0 = _mm_xor_si128(b0, b0);\
a0 = _mm_shuffle_epi8(a0, (SUBSH_MASK[0]));\
a0 = _mm_aesenclast_si128(a0, b0);\
a1 = _mm_shuffle_epi8(a1, (SUBSH_MASK[1]));\
a1 = _mm_aesenclast_si128(a1, b0);\
a2 = _mm_shuffle_epi8(a2, (SUBSH_MASK[2]));\
a2 = _mm_aesenclast_si128(a2, b0);\
a3 = _mm_shuffle_epi8(a3, (SUBSH_MASK[3]));\
a3 = _mm_aesenclast_si128(a3, b0);\
a4 = _mm_shuffle_epi8(a4, (SUBSH_MASK[4]));\
a4 = _mm_aesenclast_si128(a4, b0);\
a5 = _mm_shuffle_epi8(a5, (SUBSH_MASK[5]));\
a5 = _mm_aesenclast_si128(a5, b0);\
a6 = _mm_shuffle_epi8(a6, (SUBSH_MASK[6]));\
a6 = _mm_aesenclast_si128(a6, b0);\
a7 = _mm_shuffle_epi8(a7, (SUBSH_MASK[7]));\
a7 = _mm_aesenclast_si128(a7, b0);\
b0 = _mm512_xor_si512( b0, b0 );\
a0 = _mm512_shuffle_epi8( a0, (SUBSH_MASK[0]) );\
a0 = _mm512_aesenclast_epi128(a0, b0 );\
a1 = _mm512_shuffle_epi8( a1, (SUBSH_MASK[1]) );\
a1 = _mm512_aesenclast_epi128(a1, b0 );\
a2 = _mm512_shuffle_epi8( a2, (SUBSH_MASK[2]) );\
a2 = _mm512_aesenclast_epi128(a2, b0 );\
a3 = _mm512_shuffle_epi8( a3, (SUBSH_MASK[3]) );\
a3 = _mm512_aesenclast_epi128(a3, b0 );\
a4 = _mm512_shuffle_epi8( a4, (SUBSH_MASK[4]) );\
a4 = _mm512_aesenclast_epi128(a4, b0 );\
a5 = _mm512_shuffle_epi8( a5, (SUBSH_MASK[5]) );\
a5 = _mm512_aesenclast_epi128(a5, b0 );\
a6 = _mm512_shuffle_epi8( a6, (SUBSH_MASK[6]) );\
a6 = _mm512_aesenclast_epi128(a6, b0 );\
a7 = _mm512_shuffle_epi8( a7, (SUBSH_MASK[7]) );\
a7 = _mm512_aesenclast_epi128( a7, b0 );\
\
/* MixBytes */\
MixBytes(a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7);\
@@ -237,31 +275,31 @@ __m128i ALL_FF;
#define Matrix_Transpose_A(i0, i1, i2, i3, o1, o2, o3, t0){\
t0 = TRANSP_MASK;\
\
i0 = _mm_shuffle_epi8(i0, t0);\
i1 = _mm_shuffle_epi8(i1, t0);\
i2 = _mm_shuffle_epi8(i2, t0);\
i3 = _mm_shuffle_epi8(i3, t0);\
i0 = _mm512_shuffle_epi8( i0, t0 );\
i1 = _mm512_shuffle_epi8( i1, t0 );\
i2 = _mm512_shuffle_epi8( i2, t0 );\
i3 = _mm512_shuffle_epi8( i3, t0 );\
\
o1 = i0;\
t0 = i2;\
\
i0 = _mm_unpacklo_epi16(i0, i1);\
o1 = _mm_unpackhi_epi16(o1, i1);\
i2 = _mm_unpacklo_epi16(i2, i3);\
t0 = _mm_unpackhi_epi16(t0, i3);\
i0 = _mm512_unpacklo_epi16( i0, i1 );\
o1 = _mm512_unpackhi_epi16( o1, i1 );\
i2 = _mm512_unpacklo_epi16( i2, i3 );\
t0 = _mm512_unpackhi_epi16( t0, i3 );\
\
i0 = _mm_shuffle_epi32(i0, 216);\
o1 = _mm_shuffle_epi32(o1, 216);\
i2 = _mm_shuffle_epi32(i2, 216);\
t0 = _mm_shuffle_epi32(t0, 216);\
i0 = _mm512_shuffle_epi32( i0, 216 );\
o1 = _mm512_shuffle_epi32( o1, 216 );\
i2 = _mm512_shuffle_epi32( i2, 216 );\
t0 = _mm512_shuffle_epi32( t0, 216 );\
\
o2 = i0;\
o3 = o1;\
\
i0 = _mm_unpacklo_epi32(i0, i2);\
o1 = _mm_unpacklo_epi32(o1, t0);\
o2 = _mm_unpackhi_epi32(o2, i2);\
o3 = _mm_unpackhi_epi32(o3, t0);\
i0 = _mm512_unpacklo_epi32( i0, i2 );\
o1 = _mm512_unpacklo_epi32( o1, t0 );\
o2 = _mm512_unpackhi_epi32( o2, i2 );\
o3 = _mm512_unpackhi_epi32( o3, t0 );\
}/**/
/* Matrix Transpose Step 2
@@ -279,19 +317,19 @@ __m128i ALL_FF;
#define Matrix_Transpose_B(i0, i1, i2, i3, i4, i5, i6, i7, o1, o2, o3, o4, o5, o6, o7){\
o1 = i0;\
o2 = i1;\
i0 = _mm_unpacklo_epi64(i0, i4);\
o1 = _mm_unpackhi_epi64(o1, i4);\
i0 = _mm512_unpacklo_epi64( i0, i4 );\
o1 = _mm512_unpackhi_epi64( o1, i4 );\
o3 = i1;\
o4 = i2;\
o2 = _mm_unpacklo_epi64(o2, i5);\
o3 = _mm_unpackhi_epi64(o3, i5);\
o2 = _mm512_unpacklo_epi64( o2, i5 );\
o3 = _mm512_unpackhi_epi64( o3, i5 );\
o5 = i2;\
o6 = i3;\
o4 = _mm_unpacklo_epi64(o4, i6);\
o5 = _mm_unpackhi_epi64(o5, i6);\
o4 = _mm512_unpacklo_epi64( o4, i6 );\
o5 = _mm512_unpackhi_epi64( o5, i6 );\
o7 = i3;\
o6 = _mm_unpacklo_epi64(o6, i7);\
o7 = _mm_unpackhi_epi64(o7, i7);\
o6 = _mm512_unpacklo_epi64( o6, i7 );\
o7 = _mm512_unpackhi_epi64( o7, i7 );\
}/**/
/* Matrix Transpose Inverse Step 2
@@ -302,19 +340,20 @@ __m128i ALL_FF;
*/
#define Matrix_Transpose_B_INV(i0, i1, i2, i3, i4, i5, i6, i7, o0, o1, o2, o3){\
o0 = i0;\
i0 = _mm_unpacklo_epi64(i0, i1);\
o0 = _mm_unpackhi_epi64(o0, i1);\
i0 = _mm512_unpacklo_epi64( i0, i1 );\
o0 = _mm512_unpackhi_epi64( o0, i1 );\
o1 = i2;\
i2 = _mm_unpacklo_epi64(i2, i3);\
o1 = _mm_unpackhi_epi64(o1, i3);\
i2 = _mm512_unpacklo_epi64( i2, i3 );\
o1 = _mm512_unpackhi_epi64( o1, i3 );\
o2 = i4;\
i4 = _mm_unpacklo_epi64(i4, i5);\
o2 = _mm_unpackhi_epi64(o2, i5);\
i4 = _mm512_unpacklo_epi64( i4, i5 );\
o2 = _mm512_unpackhi_epi64( o2, i5 );\
o3 = i6;\
i6 = _mm_unpacklo_epi64(i6, i7);\
o3 = _mm_unpackhi_epi64(o3, i7);\
i6 = _mm512_unpacklo_epi64( i6, i7 );\
o3 = _mm512_unpackhi_epi64( o3, i7 );\
}/**/
/* Matrix Transpose Output Step 2
* input is one 512-bit state with two rows in one xmm
* output is one 512-bit state with one row in the low 64-bits of one xmm
@@ -322,19 +361,19 @@ __m128i ALL_FF;
* outputs: (i0-7) = (0|S)
*/
#define Matrix_Transpose_O_B(i0, i1, i2, i3, i4, i5, i6, i7, t0){\
t0 = _mm_xor_si128(t0, t0);\
t0 = _mm512_xor_si512( t0, t0 );\
i1 = i0;\
i3 = i2;\
i5 = i4;\
i7 = i6;\
i0 = _mm_unpacklo_epi64(i0, t0);\
i1 = _mm_unpackhi_epi64(i1, t0);\
i2 = _mm_unpacklo_epi64(i2, t0);\
i3 = _mm_unpackhi_epi64(i3, t0);\
i4 = _mm_unpacklo_epi64(i4, t0);\
i5 = _mm_unpackhi_epi64(i5, t0);\
i6 = _mm_unpacklo_epi64(i6, t0);\
i7 = _mm_unpackhi_epi64(i7, t0);\
i0 = _mm512_unpacklo_epi64( i0, t0 );\
i1 = _mm512_unpackhi_epi64( i1, t0 );\
i2 = _mm512_unpacklo_epi64( i2, t0 );\
i3 = _mm512_unpackhi_epi64( i3, t0 );\
i4 = _mm512_unpacklo_epi64( i4, t0 );\
i5 = _mm512_unpackhi_epi64( i5, t0 );\
i6 = _mm512_unpacklo_epi64( i6, t0 );\
i7 = _mm512_unpackhi_epi64( i7, t0 );\
}/**/
/* Matrix Transpose Output Inverse Step 2
@@ -344,17 +383,18 @@ __m128i ALL_FF;
* outputs: (i0, i2, i4, i6) = S
*/
#define Matrix_Transpose_O_B_INV(i0, i1, i2, i3, i4, i5, i6, i7){\
i0 = _mm_unpacklo_epi64(i0, i1);\
i2 = _mm_unpacklo_epi64(i2, i3);\
i4 = _mm_unpacklo_epi64(i4, i5);\
i6 = _mm_unpacklo_epi64(i6, i7);\
i0 = _mm512_unpacklo_epi64( i0, i1 );\
i2 = _mm512_unpacklo_epi64( i2, i3 );\
i4 = _mm512_unpacklo_epi64( i4, i5 );\
i6 = _mm512_unpacklo_epi64( i6, i7 );\
}/**/
void INIT256( __m128i* chaining )
void INIT256_4way( __m512i* chaining )
{
static __m128i xmm0, /*xmm1,*/ xmm2, /*xmm3, xmm4, xmm5,*/ xmm6, xmm7;
static __m128i /*xmm8, xmm9, xmm10, xmm11,*/ xmm12, xmm13, xmm14, xmm15;
static __m512i xmm0, xmm2, xmm6, xmm7;
static __m512i xmm12, xmm13, xmm14, xmm15;
/* load IV into registers xmm12 - xmm15 */
xmm12 = chaining[0];
@@ -373,17 +413,13 @@ void INIT256( __m128i* chaining )
chaining[3] = xmm7;
}
void TF512( __m128i* chaining, __m128i* message )
void TF512_4way( __m512i* chaining, __m512i* message )
{
static __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
static __m128i xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
static __m128i TEMP0;
static __m128i TEMP1;
static __m128i TEMP2;
#ifdef IACA_TRACE
IACA_START;
#endif
static __m512i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
static __m512i xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
static __m512i TEMP0;
static __m512i TEMP1;
static __m512i TEMP2;
/* load message into registers xmm12 - xmm15 */
xmm12 = message[0];
@@ -404,10 +440,10 @@ void TF512( __m128i* chaining, __m128i* message )
/* xor message to CV get input of P */
/* result: CV+M in xmm8, xmm0, xmm4, xmm5 */
xmm8 = _mm_xor_si128(xmm8, xmm12);
xmm0 = _mm_xor_si128(xmm0, xmm2);
xmm4 = _mm_xor_si128(xmm4, xmm6);
xmm5 = _mm_xor_si128(xmm5, xmm7);
xmm8 = _mm512_xor_si512( xmm8, xmm12 );
xmm0 = _mm512_xor_si512( xmm0, xmm2 );
xmm4 = _mm512_xor_si512( xmm4, xmm6 );
xmm5 = _mm512_xor_si512( xmm5, xmm7 );
/* there are now 2 rows of the Groestl state (P and Q) in each xmm register */
/* unpack to get 1 row of P (64 bit) and Q (64 bit) into one xmm register */
@@ -422,17 +458,17 @@ void TF512( __m128i* chaining, __m128i* message )
/* xor output of P and Q */
/* result: P(CV+M)+Q(M) in xmm0...xmm3 */
xmm0 = _mm_xor_si128(xmm0, xmm8);
xmm1 = _mm_xor_si128(xmm1, xmm10);
xmm2 = _mm_xor_si128(xmm2, xmm12);
xmm3 = _mm_xor_si128(xmm3, xmm14);
xmm0 = _mm512_xor_si512( xmm0, xmm8 );
xmm1 = _mm512_xor_si512( xmm1, xmm10 );
xmm2 = _mm512_xor_si512( xmm2, xmm12 );
xmm3 = _mm512_xor_si512( xmm3, xmm14 );
/* xor CV (feed-forward) */
/* result: P(CV+M)+Q(M)+CV in xmm0...xmm3 */
xmm0 = _mm_xor_si128(xmm0, (chaining[0]));
xmm1 = _mm_xor_si128(xmm1, (chaining[1]));
xmm2 = _mm_xor_si128(xmm2, (chaining[2]));
xmm3 = _mm_xor_si128(xmm3, (chaining[3]));
xmm0 = _mm512_xor_si512( xmm0, (chaining[0]) );
xmm1 = _mm512_xor_si512( xmm1, (chaining[1]) );
xmm2 = _mm512_xor_si512( xmm2, (chaining[2]) );
xmm3 = _mm512_xor_si512( xmm3, (chaining[3]) );
/* store CV */
chaining[0] = xmm0;
@@ -440,19 +476,16 @@ void TF512( __m128i* chaining, __m128i* message )
chaining[2] = xmm2;
chaining[3] = xmm3;
#ifdef IACA_TRACE
IACA_END;
#endif
return;
}
void OF512( __m128i* chaining )
void OF512_4way( __m512i* chaining )
{
static __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
static __m128i xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
static __m128i TEMP0;
static __m128i TEMP1;
static __m128i TEMP2;
static __m512i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
static __m512i xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
static __m512i TEMP0;
static __m512i TEMP1;
static __m512i TEMP2;
/* load CV into registers xmm8, xmm10, xmm12, xmm14 */
xmm8 = chaining[0];
@@ -475,10 +508,10 @@ void OF512( __m128i* chaining )
/* xor CV to P output (feed-forward) */
/* result: P(CV)+CV in xmm8, xmm10, xmm12, xmm14 */
xmm8 = _mm_xor_si128(xmm8, (chaining[0]));
xmm10 = _mm_xor_si128(xmm10, (chaining[1]));
xmm12 = _mm_xor_si128(xmm12, (chaining[2]));
xmm14 = _mm_xor_si128(xmm14, (chaining[3]));
xmm8 = _mm512_xor_si512( xmm8, (chaining[0]) );
xmm10 = _mm512_xor_si512( xmm10, (chaining[1]) );
xmm12 = _mm512_xor_si512( xmm12, (chaining[2]) );
xmm14 = _mm512_xor_si512( xmm14, (chaining[3]) );
/* transform state back from row ordering into column ordering */
/* result: final hash value in xmm9, xmm11 */
@@ -489,4 +522,5 @@ void OF512( __m128i* chaining )
chaining[3] = xmm11;
}
#endif // VAES
#endif // GROESTL512_INTR_4WAY_H__

View File

@@ -15,38 +15,22 @@
#include "miner.h"
#include "simd-utils.h"
#if defined(__VAES__)
#define ROTL64(a,n) \
( ( ( (a)<<(n) ) | ( (a) >> (64-(n)) ) ) & 0xffffffffffffffff )
#define U64BIG(a) \
( ( ROTL64(a, 8) & 0x000000FF000000FF ) | \
( ROTL64(a,24) & 0x0000FF000000FF00 ) | \
( ROTL64(a,40) & 0x00FF000000FF0000 ) | \
( ROTL64(a,56) & 0xFF000000FF000000 ) )
#if defined(__VAES__) && defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__)
int groestl512_4way_init( groestl512_4way_context* ctx, uint64_t hashlen )
{
int i;
ctx->hashlen = hashlen;
SET_CONSTANTS();
if (ctx->chaining == NULL || ctx->buffer == NULL)
return 1;
for ( i = 0; i < SIZE512; i++ )
{
ctx->chaining[i] = m512_zero;
ctx->buffer[i] = m512_zero;
}
memset_zero_512( ctx->chaining, SIZE512 );
memset_zero_512( ctx->buffer, SIZE512 );
// The only non-zero in the IV is len. It can be hard coded.
ctx->chaining[ 6 ] = m512_const2_64( 0x0200000000000000, 0 );
// uint64_t len = U64BIG((uint64_t)LENGTH);
// ctx->chaining[ COLS/2 -1 ] = _mm512_set4_epi64( len, 0, len, 0 );
// INIT_4way(ctx->chaining);
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
@@ -58,7 +42,7 @@ int groestl512_4way_update_close( groestl512_4way_context* ctx, void* output,
const void* input, uint64_t databitlen )
{
const int len = (int)databitlen / 128;
const int hashlen_m128i = ctx->hashlen / 16; // bytes to __m128i
const int hashlen_m128i = 64 / 16; // bytes to __m128i
const int hash_offset = SIZE512 - hashlen_m128i;
int rem = ctx->rem_ptr;
int blocks = len / SIZE512;
@@ -67,16 +51,13 @@ int groestl512_4way_update_close( groestl512_4way_context* ctx, void* output,
// --- update ---
// digest any full blocks, process directly from input
for ( i = 0; i < blocks; i++ )
TF1024_4way( ctx->chaining, &in[ i * SIZE512 ] );
ctx->buf_ptr = blocks * SIZE512;
// copy any remaining data to buffer, it may already contain data
// from a previous update for a midstate precalc
for ( i = 0; i < len % SIZE512; i++ )
ctx->buffer[ rem + i ] = in[ ctx->buf_ptr + i ];
i += rem; // use i as rem_ptr in final
i += rem;
//--- final ---
@@ -90,23 +71,71 @@ int groestl512_4way_update_close( groestl512_4way_context* ctx, void* output,
}
else
{
// add first padding
ctx->buffer[i] = m512_const4_64( 0, 0x80, 0, 0x80 );
// add zero padding
for ( i += 1; i < SIZE512 - 1; i++ )
ctx->buffer[i] = m512_zero;
// add length padding, second last byte is zero unless blocks > 255
ctx->buffer[i] = m512_const1_128( _mm_set_epi8(
blocks, blocks>>8, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 ) );
}
// digest final padding block and do output transform
TF1024_4way( ctx->chaining, ctx->buffer );
OF1024_4way( ctx->chaining );
// store hash result in output
for ( i = 0; i < hashlen_m128i; i++ )
casti_m512i( output, i ) = ctx->chaining[ hash_offset + i ];
return 0;
}
int groestl512_4way_full( groestl512_4way_context* ctx, void* output,
const void* input, uint64_t datalen )
{
const int len = (int)datalen >> 4;
const int hashlen_m128i = 64 >> 4; // bytes to __m128i
const int hash_offset = SIZE512 - hashlen_m128i;
uint64_t blocks = len / SIZE512;
__m512i* in = (__m512i*)input;
int i;
// --- init ---
SET_CONSTANTS();
memset_zero_512( ctx->chaining, SIZE512 );
memset_zero_512( ctx->buffer, SIZE512 );
ctx->chaining[ 6 ] = m512_const2_64( 0x0200000000000000, 0 );
ctx->buf_ptr = 0;
ctx->rem_ptr = 0;
// --- update ---
for ( i = 0; i < blocks; i++ )
TF1024_4way( ctx->chaining, &in[ i * SIZE512 ] );
ctx->buf_ptr = blocks * SIZE512;
for ( i = 0; i < len % SIZE512; i++ )
ctx->buffer[ ctx->rem_ptr + i ] = in[ ctx->buf_ptr + i ];
i += ctx->rem_ptr;
// --- close ---
blocks++;
if ( i == SIZE512 - 1 )
{
// only 1 vector left in buffer, all padding at once
ctx->buffer[i] = m512_const2_64( blocks << 56, 0x80 );
}
else
{
ctx->buffer[i] = m512_const4_64( 0, 0x80, 0, 0x80 );
for ( i += 1; i < SIZE512 - 1; i++ )
ctx->buffer[i] = m512_zero;
ctx->buffer[i] = m512_const2_64( blocks << 56, 0 );
}
TF1024_4way( ctx->chaining, ctx->buffer );
OF1024_4way( ctx->chaining );
for ( i = 0; i < hashlen_m128i; i++ )
casti_m512i( output, i ) = ctx->chaining[ hash_offset + i ];

View File

@@ -1,11 +1,3 @@
/* hash.h Aug 2011
*
* Groestl implementation for different versions.
* Author: Krystian Matusiewicz, Günther A. Roland, Martin Schläffer
*
* This code is placed in the public domain
*/
#if !defined(GROESTL512_HASH_4WAY_H__)
#define GROESTL512_HASH_4WAY_H__ 1
@@ -18,11 +10,9 @@
#endif
#include <stdlib.h>
#define LENGTH (512)
#if defined(__VAES__) && defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && defined(__AVX512BW__)
//#include "brg_endian.h"
//#define NEED_UINT_64T
//#include "algo/sha/brg_types.h"
#define LENGTH (512)
/* some sizes (number of bytes) */
#define ROWS (8)
@@ -44,34 +34,11 @@
#define ROUNDS (ROUNDS1024)
//#endif
/*
#define ROTL64(a,n) ((((a)<<(n))|((a)>>(64-(n))))&li_64(ffffffffffffffff))
#if (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN)
#define EXT_BYTE(var,n) ((u8)((u64)(var) >> (8*(7-(n)))))
#define U64BIG(a) (a)
#endif // IS_BIG_ENDIAN
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
#define EXT_BYTE(var,n) ((u8)((u64)(var) >> (8*n)))
#define U64BIG(a) \
((ROTL64(a, 8) & li_64(000000FF000000FF)) | \
(ROTL64(a,24) & li_64(0000FF000000FF00)) | \
(ROTL64(a,40) & li_64(00FF000000FF0000)) | \
(ROTL64(a,56) & li_64(FF000000FF000000)))
#endif // IS_LITTLE_ENDIAN
typedef unsigned char BitSequence_gr;
typedef unsigned long long DataLength_gr;
typedef enum { SUCCESS_GR = 0, FAIL_GR = 1, BAD_HASHBITLEN_GR = 2} HashReturn_gr;
*/
#define SIZE512 (SIZE_1024/16)
typedef struct {
__attribute__ ((aligned (128))) __m512i chaining[SIZE512];
__attribute__ ((aligned (64))) __m512i buffer[SIZE512];
int hashlen; // byte
int blk_count; // SIZE_m128i
int buf_ptr; // __m128i offset
int rem_ptr;
@@ -85,10 +52,11 @@ int groestl512_4way_init( groestl512_4way_context*, uint64_t );
int groestl512_4way_update( groestl512_4way_context*, const void*,
uint64_t );
int groestl512_4way_close( groestl512_4way_context*, void* );
int groestl512_4way_update_close( groestl512_4way_context*, void*,
const void*, uint64_t );
int groestl512_4way_full( groestl512_4way_context*, void*,
const void*, uint64_t );
#endif /* __hash_h */
#endif // VAES
#endif // GROESTL512_HASH_4WAY_H__

View File

@@ -1,22 +1,20 @@
#include "myrgr-gate.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifdef NO_AES_NI
#include "sph_groestl.h"
#else
#ifdef __AES__
#include "aes_ni/hash-groestl.h"
#else
#include "sph_groestl.h"
#endif
#include <openssl/sha.h>
typedef struct {
#ifdef NO_AES_NI
sph_groestl512_context groestl;
#else
#ifdef __AES__
hashState_groestl groestl;
#else
sph_groestl512_context groestl;
#endif
SHA256_CTX sha;
} myrgr_ctx_holder;
@@ -25,10 +23,10 @@ myrgr_ctx_holder myrgr_ctx;
void init_myrgr_ctx()
{
#ifdef NO_AES_NI
sph_groestl512_init( &myrgr_ctx.groestl );
#else
#ifdef __AES__
init_groestl ( &myrgr_ctx.groestl, 64 );
#else
sph_groestl512_init( &myrgr_ctx.groestl );
#endif
SHA256_Init( &myrgr_ctx.sha );
}
@@ -40,12 +38,12 @@ void myriad_hash(void *output, const void *input)
uint32_t _ALIGN(32) hash[16];
#ifdef NO_AES_NI
sph_groestl512(&ctx.groestl, input, 80);
sph_groestl512_close(&ctx.groestl, hash);
#else
#ifdef __AES__
update_groestl( &ctx.groestl, (char*)input, 640 );
final_groestl( &ctx.groestl, (char*)hash);
#else
sph_groestl512(&ctx.groestl, input, 80);
sph_groestl512_close(&ctx.groestl, hash);
#endif
SHA256_Update( &ctx.sha, (unsigned char*)hash, 64 );