/*
 * Based on John the Ripper and modified to integrate with aircrack
 *
 * 	John the Ripper copyright and license.
 *
 * John the Ripper password cracker,
 * Copyright (c) 1996-2013 by Solar Designer.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * As a special exception to the GNU General Public License terms,
 * permission is hereby granted to link the code of this program, with or
 * without modification, with any version of the OpenSSL library and/or any
 * version of unRAR, and to distribute such linked combinations.  You must
 * obey the GNU GPL in all respects for all of the code used other than
 * OpenSSL and unRAR.  If you modify this program, you may extend this
 * exception to your version of the program, but you are not obligated to
 * do so.  (In other words, you may release your derived work under pure
 * GNU GPL version 2 or later as published by the FSF.)
 *
 * (This exception from the GNU GPL is not required for the core tree of
 * John the Ripper, but arguably it is required for -jumbo.)
 *
 * 	Relaxed terms for certain components.
 *
 * In addition or alternatively to the license above, many components are
 * available to you under more relaxed terms (most commonly under cut-down
 * BSD license) as specified in the corresponding source files.
 *
 * For more information on John the Ripper licensing please visit:
 *
 * http://www.openwall.com/john/doc/LICENSE.shtml
 *
 * This file is part of John the Ripper password cracker,
 * Copyright (c) 2003,2006,2008,2010,2011,2015 by Solar Designer
 *
 * ...with a trivial change in the jumbo patch, by Alain Espinosa.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted.
 *
 * There's ABSOLUTELY NO WARRANTY, express or implied.
 */

/*
 * Architecture specific parameters for x86-64.
 */

#ifndef _ARCH_H
#define _ARCH_H

#if (defined(__ARM_NEON) && !defined(__ARM_NEON__)) || defined(__aarch64)      \
	|| defined(__aarch64__)
#define __ARM_NEON__ 1
#endif

#if (defined(__ARM_NEON__) && !defined(__ARM_NEON)) || defined(__aarch64)      \
	|| defined(__aarch64__)
#define __ARM_NEON 1
#endif

#ifdef __ARM_NEON__
#define SHA_BUF_SIZ 16
#define SIMD_COEF_32 4
#define SIMD_COEF_64 2
#ifndef SIMD_PARA_SHA1
#define SIMD_PARA_SHA1 1
#endif
#ifndef SIMD_PARA_SHA256
#define SIMD_PARA_SHA256 0
#endif
#ifndef SIMD_PARA_SHA512
#define SIMD_PARA_SHA512 0
#endif
#endif

#if defined(JOHN_ALTIVEC)
#define SHA_BUF_SIZ 16
#define SIMD_COEF_32 4
#define SIMD_COEF_64 2
#ifndef SIMD_PARA_SHA1
#define SIMD_PARA_SHA1 1
#endif
#ifndef SIMD_PARA_SHA256
#define SIMD_PARA_SHA256 0
#endif
#ifndef SIMD_PARA_SHA512
#define SIMD_PARA_SHA512 0
#endif

#endif

#if AC_BUILT
#include "autoconfig.h"
#else
#if defined(__ILP32__) || defined(_WIN64) || defined(__LLP64__)                \
	|| (defined(__SIZE_OF_LONG__) && __SIZEOF_LONG__ == 4)
#define ARCH_WORD long long
#else
#define ARCH_WORD long
#endif
#define ARCH_SIZE 8
#define ARCH_BITS 64
#define ARCH_BITS_LOG 6
#define ARCH_BITS_STR "64"
#define ARCH_LITTLE_ENDIAN 1
#define ARCH_INT_GT_32 0
#endif

#define ARCH_ALLOWS_UNALIGNED 1
#define ARCH_INDEX(x) ((unsigned int) (unsigned char) (x))

#define CPU_DETECT 0

#ifdef __SSE2__
#define CPU_NAME "SSE2"
#endif

#if __SSSE3__ || JOHN_SSSE3
#undef CPU_DETECT
#define CPU_DETECT 1
#define CPU_REQ 1
#define CPU_REQ_SSSE3 1
#undef CPU_NAME
#define CPU_NAME "SSSE3"
#if CPU_FALLBACK && !defined(CPU_FALLBACK_BINARY)
#define CPU_FALLBACK_BINARY "john-non-ssse3"
#define CPU_FALLBACK_BINARY_DEFAULT
#endif
#endif

#if __SSE4_1__ || JOHN_SSE4_1
#undef CPU_DETECT
#define CPU_DETECT 1
#define CPU_REQ 1
#define CPU_REQ_SSE4_1 1
#undef CPU_NAME
#define CPU_NAME "SSE4.1"
#if CPU_FALLBACK && !defined(CPU_FALLBACK_BINARY)
#define CPU_FALLBACK_BINARY "john-non-sse4.1"
#define CPU_FALLBACK_BINARY_DEFAULT
#endif
#endif

#if __AVX512F__ || JOHN_AVX512F
#undef CPU_DETECT
#define CPU_DETECT 1
#define CPU_REQ 1
#define CPU_REQ_AVX512F 1
#undef CPU_NAME
#define CPU_NAME "AVX512F"
#if CPU_FALLBACK && !defined(CPU_FALLBACK_BINARY)
#define CPU_FALLBACK_BINARY "john-non-avx512f"
#define CPU_FALLBACK_BINARY_DEFAULT
#endif
#endif

#if __AVX512BW__ || JOHN_AVX512BW
#undef CPU_DETECT
#define CPU_DETECT 1
#define CPU_REQ 1
#define CPU_REQ_AVX512BW 1
#undef CPU_NAME
#define CPU_NAME "AVX512BW"
#if CPU_FALLBACK && !defined(CPU_FALLBACK_BINARY)
#define CPU_FALLBACK_BINARY "john-non-avx512bw"
#define CPU_FALLBACK_BINARY_DEFAULT
#endif
#endif

#ifdef __XOP__
#define JOHN_XOP 1
#endif
#if defined(__AVX__) || defined(JOHN_XOP) || defined(JOHN_AVX2)
#define JOHN_AVX 1
#endif

#define DES_ASM 0
#define DES_128K 0
#define DES_X2 0
#define DES_MASK 1
#define DES_SCALE 1
#define DES_EXTB 1
#define DES_COPY 0
#define DES_BS 1
#if !defined(__SSE2__)
#define DES_BS_VECTOR 0
#define DES_BS_ALGORITHM_NAME "DES 64/64"
#elif defined(JOHN_AVX) && (defined(__GNUC__) || defined(_OPENMP))
/*
 * Require gcc for AVX/XOP because DES_bs_all is aligned in a gcc-specific way,
 * except in OpenMP-enabled builds, where it's aligned by different means.
 */
#undef CPU_DETECT
#define CPU_DETECT 1
#define CPU_REQ 1
#define CPU_REQ_AVX 1
#undef CPU_NAME
#define CPU_NAME "AVX"
#if CPU_FALLBACK && !defined(CPU_FALLBACK_BINARY)
#define CPU_FALLBACK_BINARY "john-non-avx"
#define CPU_FALLBACK_BINARY_DEFAULT
#endif
#define DES_BS_ASM 0
#if 0
/* 512-bit as 2x256 */
#define DES_BS_VECTOR 8
#if defined(JOHN_XOP) && defined(__GNUC__)
/* Require gcc for 256-bit XOP because of __builtin_ia32_vpcmov_v8sf256() */
#undef DES_BS
#define DES_BS 3
#define DES_BS_ALGORITHM_NAME "DES 256/256 X2 XOP-16"
#else
#define DES_BS_ALGORITHM_NAME "DES 256/256 X2 AVX-16"
#endif
#elif 0
/* 384-bit as 256+128 */
#define DES_BS_VECTOR_SIZE 8
#define DES_BS_VECTOR 6
#if defined(JOHN_XOP) && defined(__GNUC__)
/* Require gcc for 256-bit XOP because of __builtin_ia32_vpcmov_v8sf256() */
#undef DES_BS
#define DES_BS 3
#define DES_BS_ALGORITHM_NAME "DES 256/256 XOP-16 + 128/128 XOP-16"
#else
#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX-16 + 128/128 AVX-16"
#endif
#elif 0
/* 384-bit as 256+64+64 */
#define DES_BS_NO_AVX128
#define DES_BS_VECTOR_SIZE 8
#define DES_BS_VECTOR 6
#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX-16 + 64/64 MMX + 64/64"
#elif 0
/* 320-bit as 256+64 MMX */
#define DES_BS_VECTOR_SIZE 8
#define DES_BS_VECTOR 5
#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX-16 + 64/64 MMX"
#elif 0
/* 320-bit as 256+64 */
#define DES_BS_NO_MMX
#define DES_BS_VECTOR_SIZE 8
#define DES_BS_VECTOR 5
#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX-16 + 64/64"
#elif __AVX2__ || JOHN_AVX2
/* 256-bit as 1x256 */
#define DES_BS_VECTOR 4
#undef CPU_NAME
#define CPU_NAME "AVX2"
#define CPU_DETECT 1
#define CPU_REQ 1
#define CPU_REQ_AVX2 1
#if CPU_FALLBACK && !defined(CPU_FALLBACK_BINARY)
#define CPU_FALLBACK_BINARY "john-non-avx2"
#define CPU_FALLBACK_BINARY_DEFAULT
#endif
#define DES_BS_ALGORITHM_NAME "DES 256/256 AVX2-16"
#elif 0
/* 256-bit as 2x128 */
#define DES_BS_NO_AVX256
#define DES_BS_VECTOR 4
#ifdef JOHN_XOP
#undef DES_BS
#define DES_BS 3
#define DES_BS_ALGORITHM_NAME "DES 128/128 X2 XOP-16"
#else
#define DES_BS_ALGORITHM_NAME "DES 128/128 X2 AVX-16"
#endif
#else
/* 128-bit */
#define DES_BS_VECTOR 2
#ifdef JOHN_XOP
#undef DES_BS
#define DES_BS 3
#define DES_BS_ALGORITHM_NAME "DES 128/128 XOP-16"
#else
#define DES_BS_ALGORITHM_NAME "DES 128/128 AVX-16"
#endif
#endif
#elif (defined(__SSE2__) && defined(_OPENMP))
#define DES_BS_ASM 0
#if 1
#define DES_BS_VECTOR 2
#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16"
#elif 0
#define DES_BS_VECTOR 3
#define DES_BS_VECTOR_SIZE 4
#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16 + 64/64 MMX"
#elif 0
#define DES_BS_NO_MMX
#define DES_BS_VECTOR 3
#define DES_BS_VECTOR_SIZE 4
#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16 + 64/64"
#elif 0
#define DES_BS_NO_MMX
#define DES_BS_VECTOR 4
#define DES_BS_ALGORITHM_NAME "DES 128/128 X2 SSE2-16"
#else
#define DES_BS_VECTOR 4
#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16 + 64/64 MMX + 64/64"
#endif
#else
#define DES_BS_ASM 1
#define DES_BS_VECTOR 2
#define DES_BS_ALGORITHM_NAME "DES 128/128 SSE2-16"
#endif
#define DES_BS_EXPAND 1

#if CPU_DETECT && DES_BS == 3
#define CPU_REQ_XOP 1
#undef CPU_NAME
#define CPU_NAME "XOP"
#ifdef CPU_FALLBACK_BINARY_DEFAULT
#undef CPU_FALLBACK_BINARY
#define CPU_FALLBACK_BINARY "john-non-xop"
#endif
#endif

#define MD5_ASM 0
#define MD5_X2 1
#define MD5_IMM 1

#ifdef __GNUC__
#define GCC_VERSION                                                            \
	(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif

#ifdef __SSE2__

#if __AVX512F__
#define SIMD_COEF_32 16
#define SIMD_COEF_64 8
#elif __AVX2__
#define SIMD_COEF_32 8
#define SIMD_COEF_64 4
#elif __SSE2__
#define SIMD_COEF_32 4
#define SIMD_COEF_64 2
#endif

#ifndef SIMD_PARA_SHA1
#if defined(__INTEL_COMPILER)
#define SIMD_PARA_SHA1 1
#elif defined(__clang__)
#define SIMD_PARA_SHA1 1
#elif defined(__llvm__)
#define SIMD_PARA_SHA1 1
#elif defined(__GNUC__) && GCC_VERSION < 40504 // 4.5.4
#define SIMD_PARA_SHA1 1
#elif !defined(__AVX__) && defined(__GNUC__) && GCC_VERSION > 40700 // 4.7.0
#define SIMD_PARA_SHA1 1
#else
#define SIMD_PARA_SHA1 1
#endif
#endif

#if 0
#ifndef SIMD_PARA_SHA256
#if __XOP__
#define SIMD_PARA_SHA256 2
#else
#define SIMD_PARA_SHA256 1
#endif
#endif
#ifndef SIMD_PARA_SHA512
#define SIMD_PARA_SHA512 1
#endif
#endif

#ifndef SHA1_SSE_PARA
#if defined(__INTEL_COMPILER) || defined(USING_ICC_S_FILE)
#define SHA1_SSE_PARA 1
//#define SHA1_N_STR		      "4x"
#elif defined(__clang__)
#define SHA1_SSE_PARA 2
//#define SHA1_N_STR		      "8x"
#elif defined(__llvm__)
#define SHA_BUF_SIZ 80
#define SHA1_SSE_PARA 2
//#define SHA1_N_STR		      "8x"
#elif defined(__GNUC__) && GCC_VERSION < 40504 // 4.5.4
#define SHA1_SSE_PARA 1
//#define SHA1_N_STR		      "4x"
#elif !defined(JOHN_AVX) && defined(__GNUC__) && GCC_VERSION > 40700 // 4.7.0
#define SHA1_SSE_PARA 1
//#define SHA1_N_STR		      "4x"
#else
#define SHA1_SSE_PARA 2
//#define SHA1_N_STR			"8x"
#endif
#endif

#define STR_VALUE(arg) #arg
#define PARA_TO_N(n) STR_VALUE(n) "x"
#define PARA_TO_MxN(m, n) STR_VALUE(m) "x" STR_VALUE(n)

#if SIMD_PARA_SHA1 > 1
#define SHA1_N_STR PARA_TO_MxN(SIMD_COEF_32, SIMD_PARA_SHA1)
#else
#define SHA1_N_STR PARA_TO_N(SIMD_COEF_32)
#endif
#if SIMD_PARA_SHA256 > 1
#define SHA256_N_STR PARA_TO_MxN(SIMD_COEF_32, SIMD_PARA_SHA256)
#else
#define SHA256_N_STR PARA_TO_N(SIMD_COEF_32)
#endif
#if SIMD_PARA_SHA512 > 1
#define SHA512_N_STR PARA_TO_MxN(SIMD_COEF_64, SIMD_PARA_SHA512)
#else
#define SHA512_N_STR PARA_TO_N(SIMD_COEF_64)
#endif

#define SHA_BUF_SIZ 16

#define NT_X86_64

#ifndef SIMD_CORE
#define MMX_TYPE " SSE2"
#define MMX_COEF 4
#define MMX_COEF_SHA256 4
#define MMX_COEF_SHA512 2
#endif

#endif /* __SSE2__ */

#define BF_ASM 0
#define BF_SCALE 1

/*
 * 3x (as opposed to 2x) interleaving provides substantial speedup on Core 2
 * CPUs, as well as slight speedup on some other CPUs.  Unfortunately, it
 * results in lower cumulative performance with multiple concurrent threads or
 * processes on some newer SMT-capable CPUs.  While this has nothing to do with
 * AVX per se, building for AVX implies we do not intend to run on a Core 2
 * (which has at most SSE4.1), so checking for AVX here provides an easy way to
 * avoid this performance regression in AVX-enabled builds.  In multi-binary
 * packages with runtime fallbacks, the AVX-enabled binary would invoke a
 * non-AVX fallback binary from its john.c if run e.g. on a Core 2.  We could
 * check for SSE4.2 rather than AVX here, as SSE4.2 was introduced along with
 * SMT-capable Nehalem microarchitecture CPUs, but apparently those CPUs did
 * not yet exhibit the performance regression with 3x interleaving.  Besides,
 * some newer CPUs capable of SSE4.2 but not AVX happen to lack SMT, so will
 * likely benefit from the 3x interleaving with no adverse effects for the
 * multi-threaded case.
 *
 * In Jumbo, we may get BF_X2 from autoconf (after testing ht cpuid flag).
 */
#ifndef BF_X2
#if __AVX__ && HAVE_HT && _OPENMP
#define BF_X2 1
#else
#define BF_X2 3
#endif
#endif

#endif
