xref: /freebsd/crypto/libecc/include/libecc/words/words.h (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
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