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