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