1*f0865ec9SKyle Evans /* 2*f0865ec9SKyle Evans * Copyright (C) 2017 - This file is part of libecc project 3*f0865ec9SKyle Evans * 4*f0865ec9SKyle Evans * Authors: 5*f0865ec9SKyle Evans * Ryad BENADJILA <ryadbenadjila@gmail.com> 6*f0865ec9SKyle Evans * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7*f0865ec9SKyle Evans * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8*f0865ec9SKyle Evans * 9*f0865ec9SKyle Evans * Contributors: 10*f0865ec9SKyle Evans * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11*f0865ec9SKyle Evans * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12*f0865ec9SKyle Evans * 13*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license. 14*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project. 15*f0865ec9SKyle Evans */ 16*f0865ec9SKyle Evans #ifndef __WORDS_H__ 17*f0865ec9SKyle Evans #define __WORDS_H__ 18*f0865ec9SKyle Evans 19*f0865ec9SKyle Evans /* 20*f0865ec9SKyle Evans * Types for words and a few useful macros. 21*f0865ec9SKyle Evans */ 22*f0865ec9SKyle Evans 23*f0865ec9SKyle Evans /* 24*f0865ec9SKyle Evans * If a word size is forced, we use the proper words.h definition. 25*f0865ec9SKyle Evans * By default, 64-bit word size is used since it is the most reasonable 26*f0865ec9SKyle Evans * choice across the known platforms (see below). 27*f0865ec9SKyle Evans */ 28*f0865ec9SKyle Evans 29*f0865ec9SKyle Evans #define __concat(x) #x 30*f0865ec9SKyle Evans #define _concat(file_prefix, x) __concat(file_prefix##x.h) 31*f0865ec9SKyle Evans #define concat(file_prefix, x) _concat(file_prefix, x) 32*f0865ec9SKyle Evans 33*f0865ec9SKyle Evans #if defined(WORDSIZE) 34*f0865ec9SKyle Evans /* The word size is forced by the compilation chain */ 35*f0865ec9SKyle Evans #if (WORDSIZE == 16) || (WORDSIZE == 32) || (WORDSIZE == 64) 36*f0865ec9SKyle Evans /* Dynamic include depending on the word size */ 37*f0865ec9SKyle Evans #include concat(words_, WORDSIZE) 38*f0865ec9SKyle Evans #else 39*f0865ec9SKyle Evans #error Unsupported word size concat 40*f0865ec9SKyle Evans #endif 41*f0865ec9SKyle Evans #else 42*f0865ec9SKyle Evans /* The word size is usually deduced from the known platforms. 43*f0865ec9SKyle Evans * By default when we have fast builtin uint64_t operations, 44*f0865ec9SKyle Evans * we use WORDSIZE=64. This is obviously the case on 64-bit platforms, 45*f0865ec9SKyle Evans * but this should also be the case on most 32-bit platforms where 46*f0865ec9SKyle Evans * native instructions allow a 32-bit x 32-bit to 64-bit multiplication. 47*f0865ec9SKyle Evans * 48*f0865ec9SKyle Evans * There might however be some platforms where this is not the case. 49*f0865ec9SKyle Evans * Cortex-M0/M0+ for example does not have such a native multiplication 50*f0865ec9SKyle Evans * instruction, yielding in slower code for WORDSIZE=64 than for WORDSIZE=32. 51*f0865ec9SKyle Evans * This is also the case for old Thumb ARM CPUs (pre Thumb-2). 52*f0865ec9SKyle Evans * 53*f0865ec9SKyle Evans * On 8-bit and 16-bit platform, we prefer to let the user decide on the best 54*f0865ec9SKyle Evans * option (see below)! 55*f0865ec9SKyle Evans */ 56*f0865ec9SKyle Evans #if defined(__x86_64__) || defined(__i386__) || defined(__ppc64__) || defined(__ppc__) ||\ 57*f0865ec9SKyle Evans defined(__arm__) || defined(__aarch64__) || defined(__mips__) || defined(__s390x__) ||\ 58*f0865ec9SKyle Evans defined(__SH4__) || defined(__sparc__) || defined(__riscv) 59*f0865ec9SKyle Evans #define WORDSIZE 64 60*f0865ec9SKyle Evans #include "words_64.h" 61*f0865ec9SKyle Evans #else 62*f0865ec9SKyle Evans /* We let the user fix the WORDSIZE manually */ 63*f0865ec9SKyle Evans #error "Unrecognized platform. Please specify the word size of your target (with make 16, make 32, make 64)" 64*f0865ec9SKyle Evans #endif /* Unrecognized */ 65*f0865ec9SKyle Evans #endif 66*f0865ec9SKyle Evans 67*f0865ec9SKyle Evans typedef uint8_t u8; 68*f0865ec9SKyle Evans typedef uint16_t u16; 69*f0865ec9SKyle Evans typedef uint32_t u32; 70*f0865ec9SKyle Evans typedef uint64_t u64; 71*f0865ec9SKyle Evans typedef u16 bitcnt_t; 72*f0865ec9SKyle Evans 73*f0865ec9SKyle Evans /* 74*f0865ec9SKyle Evans * Shift behavior is not defined for a shift count 75*f0865ec9SKyle Evans * higher than (WORD_BITS - 1). These macros emulate 76*f0865ec9SKyle Evans * the behavior one would expect, i.e. return 0 when 77*f0865ec9SKyle Evans * shift count is equal or more than word size. 78*f0865ec9SKyle Evans */ 79*f0865ec9SKyle Evans #define WLSHIFT(w, c) ((word_t)(((c) >= WORD_BITS) ? WORD(0) : (word_t)((w) << (c)))) 80*f0865ec9SKyle Evans #define WRSHIFT(w, c) ((word_t)(((c) >= WORD_BITS) ? WORD(0) : (word_t)((w) >> (c)))) 81*f0865ec9SKyle Evans 82*f0865ec9SKyle Evans /* To be fixed: not really constant-time. */ 83*f0865ec9SKyle Evans #define WORD_MIN(a, b) ((a) > (b) ? (b) : (a)) 84*f0865ec9SKyle Evans 85*f0865ec9SKyle Evans /* WORD_MASK[_IF[NOT]ZERO]: mask of word size and associated macros. */ 86*f0865ec9SKyle Evans #define WORD_MASK WORD_MAX 87*f0865ec9SKyle Evans 88*f0865ec9SKyle Evans /* These two macros assume two-complement representation. */ 89*f0865ec9SKyle Evans #define WORD_MASK_IFZERO(w) ((word_t)(((word_t)((w) != 0)) - WORD(1))) 90*f0865ec9SKyle Evans #define WORD_MASK_IFNOTZERO(w) ((word_t)(((word_t)((w) == 0)) - WORD(1))) 91*f0865ec9SKyle Evans 92*f0865ec9SKyle Evans #define HWORD_MASK HWORD_MAX 93*f0865ec9SKyle Evans 94*f0865ec9SKyle Evans /* WORD_HIGHBIT: constant of word size with only MSB set. */ 95*f0865ec9SKyle Evans #define WORD_HIGHBIT (WORD(1) << (WORD_BITS - 1)) 96*f0865ec9SKyle Evans 97*f0865ec9SKyle Evans /* WORD_MUL: multiply two words using schoolbook multiplication on half words */ 98*f0865ec9SKyle Evans #define WORD_MUL(outh, outl, in1, in2) do { \ 99*f0865ec9SKyle Evans word_t in1h, in1l, in2h, in2l; \ 100*f0865ec9SKyle Evans word_t tmph, tmpm, tmpl; \ 101*f0865ec9SKyle Evans word_t tmpm1, tmpm2; \ 102*f0865ec9SKyle Evans word_t carrym, carryl; \ 103*f0865ec9SKyle Evans /* Get high and low half words. */ \ 104*f0865ec9SKyle Evans in1h = (in1) >> HWORD_BITS; \ 105*f0865ec9SKyle Evans in1l = (in1) & HWORD_MASK; \ 106*f0865ec9SKyle Evans in2h = (in2) >> HWORD_BITS; \ 107*f0865ec9SKyle Evans in2l = (in2) & HWORD_MASK; \ 108*f0865ec9SKyle Evans /* Compute low product. */ \ 109*f0865ec9SKyle Evans tmpl = (word_t)(in2l * in1l); \ 110*f0865ec9SKyle Evans /* Compute middle product. */ \ 111*f0865ec9SKyle Evans tmpm1 = (word_t)(in2h * in1l); \ 112*f0865ec9SKyle Evans tmpm2 = (word_t)(in2l * in1h); \ 113*f0865ec9SKyle Evans tmpm = (word_t)(tmpm1 + tmpm2); \ 114*f0865ec9SKyle Evans /* Store middle product carry. */ \ 115*f0865ec9SKyle Evans carrym = (word_t)(tmpm < tmpm1); \ 116*f0865ec9SKyle Evans /* Compute full low product. */ \ 117*f0865ec9SKyle Evans (outl) = tmpl; \ 118*f0865ec9SKyle Evans (outl) = (word_t)((outl) + ((tmpm & HWORD_MASK) << HWORD_BITS));\ 119*f0865ec9SKyle Evans /* Store full low product carry. */ \ 120*f0865ec9SKyle Evans carryl = (word_t)((outl) < tmpl); \ 121*f0865ec9SKyle Evans /* Compute full high product. */ \ 122*f0865ec9SKyle Evans carryl = (word_t)(carryl + (tmpm >> HWORD_BITS)); \ 123*f0865ec9SKyle Evans carryl = (word_t)(carryl + (carrym << HWORD_BITS)); \ 124*f0865ec9SKyle Evans tmph = (word_t)(in2h * in1h); \ 125*f0865ec9SKyle Evans /* No carry can occur below. */ \ 126*f0865ec9SKyle Evans (outh) = (word_t)(tmph + carryl); \ 127*f0865ec9SKyle Evans } while (0) 128*f0865ec9SKyle Evans 129*f0865ec9SKyle Evans #endif /* __WORDS_H__ */ 130