• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 35418581692

18 Sep 2026 02:06PM UTC coverage: 89.801% (+0.006%) from 89.795%
35418581692

push

github

web-flow
Merge pull request #5947 from randombit/jack/simd-rev-bytes

Promote reverse_all_bytes onto SIMD_4x32

126672 of 141059 relevant lines covered (89.8%)

9330959.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.33
/src/tests/test_simd.cpp
1
/*
2
* (C) 2017 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8

9
#include <botan/hex.h>
10
#include <botan/strong_type.h>
11
#include <botan/internal/bswap.h>
12
#include <botan/internal/concat_util.h>
13
#include <botan/internal/isa_extn.h>
14
#include <botan/internal/loadstor.h>
15
#include <botan/internal/rotate.h>
16

17
#if defined(BOTAN_HAS_SIMD_4X32)
18
   #include <botan/internal/simd_4x32.h>
19
#endif
20

21
#if defined(BOTAN_HAS_SIMD_2X64)
22
   #include <botan/internal/simd_2x64.h>
23
#endif
24

25
#if defined(BOTAN_HAS_SIMD_8X32)
26
   #include <botan/internal/simd_8x32.h>
27
#endif
28

29
#if defined(BOTAN_HAS_CPUID)
30
   #include <botan/internal/cpuid.h>
31
#endif
32

33
namespace Botan_Tests {
34

35
namespace {
36

37
#if defined(BOTAN_HAS_SIMD_4X32) && defined(BOTAN_HAS_CPUID)
38

39
class SIMD_4X32_Tests final : public Test {
1✔
40
   public:
41
      std::vector<Test::Result> run() override {
1✔
42
         if(!Botan::CPUID::has(Botan::CPUID::Feature::SIMD_4X32)) {
1✔
43
            return {Test::Result::Note("simd_4x32", "Skipping tests due to missing SIMD support at runtime")};
×
44
         } else {
45
            return {test_simd_4x32()};
2✔
46
         }
47
      }
1✔
48

49
   private:
50
      Test::Result BOTAN_FN_ISA_SIMD_4X32 test_simd_4x32() {
1✔
51
         Test::Result result("SIMD_4x32");
1✔
52

53
         const uint32_t pat1 = 0xAABBCCDD;
1✔
54
         const uint32_t pat2 = 0x87654321;
1✔
55
         const uint32_t pat3 = 0x01234567;
1✔
56
         const uint32_t pat4 = 0xC0D0E0F0;
1✔
57

58
         // pat1 + pat{1,2,3,4}
59
         // precomputed to avoid integer overflow warnings
60
         const uint32_t pat1_1 = 0x557799BA;
1✔
61
         const uint32_t pat1_2 = 0x32210FFE;
1✔
62
         const uint32_t pat1_3 = 0xABDF1244;
1✔
63
         const uint32_t pat1_4 = 0x6B8CADCD;
1✔
64

65
         test_eq(result, "default init", Botan::SIMD_4x32(), 0, 0, 0, 0);
1✔
66
         test_eq(result, "SIMD scalar constructor", Botan::SIMD_4x32(1, 2, 3, 4), 1, 2, 3, 4);
1✔
67

68
         const Botan::SIMD_4x32 splat = Botan::SIMD_4x32::splat(pat1);
1✔
69

70
         test_eq(result, "splat", splat, pat1, pat1, pat1, pat1);
1✔
71

72
         const Botan::SIMD_4x32 input(pat1, pat2, pat3, pat4);
1✔
73

74
         result.test_u32_eq("SIMD_4x32::extract_word<0>", input.extract_word<0>(), pat1);
1✔
75
         result.test_u32_eq("SIMD_4x32::extract_word<1>", input.extract_word<1>(), pat2);
1✔
76
         result.test_u32_eq("SIMD_4x32::extract_word<2>", input.extract_word<2>(), pat3);
1✔
77
         result.test_u32_eq("SIMD_4x32::extract_word<3>", input.extract_word<3>(), pat4);
1✔
78

79
         const Botan::SIMD_4x32 rol = input.rotl<3>();
1✔
80

81
         test_eq(result,
1✔
82
                 "rotl",
83
                 rol,
84
                 Botan::rotl<3>(pat1),
85
                 Botan::rotl<3>(pat2),
86
                 Botan::rotl<3>(pat3),
87
                 Botan::rotl<3>(pat4));
88

89
         const Botan::SIMD_4x32 ror = input.rotr<9>();
1✔
90

91
         test_eq(result,
1✔
92
                 "rotr",
93
                 ror,
94
                 Botan::rotr<9>(pat1),
95
                 Botan::rotr<9>(pat2),
96
                 Botan::rotr<9>(pat3),
97
                 Botan::rotr<9>(pat4));
98

99
         Botan::SIMD_4x32 add = input + splat;
1✔
100
         test_eq(result, "add +", add, pat1_1, pat1_2, pat1_3, pat1_4);
1✔
101

102
         add -= splat;
1✔
103
         test_eq(result, "sub -=", add, pat1, pat2, pat3, pat4);
1✔
104

105
         add += splat;
1✔
106
         test_eq(result, "add +=", add, pat1_1, pat1_2, pat1_3, pat1_4);
1✔
107

108
         test_eq(result, "xor", input ^ splat, 0, pat2 ^ pat1, pat3 ^ pat1, pat4 ^ pat1);
1✔
109
         test_eq(result, "or", input | splat, pat1, pat2 | pat1, pat3 | pat1, pat4 | pat1);
1✔
110
         test_eq(result, "and", input & splat, pat1, pat2 & pat1, pat3 & pat1, pat4 & pat1);
1✔
111

112
         Botan::SIMD_4x32 blender = input;
1✔
113
         blender |= splat;
1✔
114
         test_eq(result, "|=", blender, pat1, pat2 | pat1, pat3 | pat1, pat4 | pat1);
1✔
115
         blender &= splat;
1✔
116
         test_eq(result, "&=", blender, pat1, pat1, pat1, pat1);
1✔
117
         blender ^= splat;
1✔
118
         test_eq(result, "^=", blender, 0, 0, 0, 0);
1✔
119

120
         blender = ~blender;
1✔
121
         test_eq(result, "~", blender, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
1✔
122

123
         blender = blender.shr<23>();
1✔
124
         test_eq(result, ">>", blender, 0x1FF, 0x1FF, 0x1FF, 0x1FF);
1✔
125

126
         blender = blender.shl<27>();
1✔
127
         test_eq(result, "<<", blender, 0xF8000000, 0xF8000000, 0xF8000000, 0xF8000000);
1✔
128

129
         blender = ~blender;
1✔
130
         test_eq(result, "~", blender, 0x7FFFFFF, 0x7FFFFFF, 0x7FFFFFF, 0x7FFFFFF);
1✔
131

132
         blender = input.andc(~blender);
1✔
133
         test_eq(
1✔
134
            result, "andc", blender, ~pat1 & 0xF8000000, ~pat2 & 0xF8000000, ~pat3 & 0xF8000000, ~pat4 & 0xF8000000);
135

136
         test_eq(result,
1✔
137
                 "bswap",
138
                 input.bswap(),
1✔
139
                 Botan::reverse_bytes(pat1),
140
                 Botan::reverse_bytes(pat2),
141
                 Botan::reverse_bytes(pat3),
142
                 Botan::reverse_bytes(pat4));
143

144
         test_eq(result,
1✔
145
                 "reverse_all_bytes",
146
                 Botan::SIMD_4x32(0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F).reverse_all_bytes(),
1✔
147
                 0x0F0E0D0C,
148
                 0x0B0A0908,
149
                 0x07060504,
150
                 0x03020100);
151

152
         Botan::SIMD_4x32 t1(pat1, pat2, pat3, pat4);
1✔
153
         Botan::SIMD_4x32 t2(pat1 + 1, pat2 + 1, pat3 + 1, pat4 + 1);
1✔
154
         Botan::SIMD_4x32 t3(pat1 + 2, pat2 + 2, pat3 + 2, pat4 + 2);
1✔
155
         Botan::SIMD_4x32 t4(pat1 + 3, pat2 + 3, pat3 + 3, pat4 + 3);
1✔
156

157
         Botan::SIMD_4x32::transpose(t1, t2, t3, t4);
1✔
158

159
         test_eq(result, "transpose t1", t1, pat1, pat1 + 1, pat1 + 2, pat1 + 3);
1✔
160
         test_eq(result, "transpose t2", t2, pat2, pat2 + 1, pat2 + 2, pat2 + 3);
1✔
161
         test_eq(result, "transpose t3", t3, pat3, pat3 + 1, pat3 + 2, pat3 + 3);
1✔
162
         test_eq(result, "transpose t4", t4, pat4, pat4 + 1, pat4 + 2, pat4 + 3);
1✔
163

164
         test_eq(result, "shift left 1", input.shift_elems_left<1>(), 0, pat1, pat2, pat3);
1✔
165
         test_eq(result, "shift left 2", input.shift_elems_left<2>(), 0, 0, pat1, pat2);
1✔
166
         test_eq(result, "shift left 3", input.shift_elems_left<3>(), 0, 0, 0, pat1);
1✔
167

168
         test_eq(result, "shift right 1", input.shift_elems_right<1>(), pat2, pat3, pat4, 0);
1✔
169
         test_eq(result, "shift right 2", input.shift_elems_right<2>(), pat3, pat4, 0, 0);
1✔
170
         test_eq(result, "shift right 3", input.shift_elems_right<3>(), pat4, 0, 0, 0);
1✔
171

172
         // Test load/stores SIMD wrapper types
173
         const auto simd_le_in = Botan::hex_decode("ABCDEF01234567890123456789ABCDEF");
1✔
174
         const auto simd_be_in = Botan::hex_decode("0123456789ABCDEFABCDEF0123456789");
1✔
175
         const auto simd_le_array_in = Botan::concat(simd_le_in, simd_be_in);
1✔
176
         const auto simd_be_array_in = Botan::concat(simd_be_in, simd_le_in);
1✔
177

178
         auto simd_le = Botan::load_le<Botan::SIMD_4x32>(simd_le_in);
1✔
179
         auto simd_be = Botan::load_be<Botan::SIMD_4x32>(simd_be_in);
1✔
180
         auto simd_le_array = Botan::load_le<std::array<Botan::SIMD_4x32, 2>>(simd_le_array_in);
1✔
181
         auto simd_be_array = Botan::load_be<std::array<Botan::SIMD_4x32, 2>>(simd_be_array_in);
1✔
182

183
         auto simd_le_vec = Botan::store_le<std::vector<uint8_t>>(simd_le);
1✔
184
         auto simd_be_vec = Botan::store_be(simd_be);
1✔
185
         auto simd_le_array_vec = Botan::store_le<std::vector<uint8_t>>(simd_le_array);
1✔
186
         auto simd_be_array_vec = Botan::store_be(simd_be_array);
1✔
187

188
         result.test_bin_eq("roundtrip SIMD little-endian", simd_le_vec, simd_le_in);
1✔
189
         result.test_bin_eq(
1✔
190
            "roundtrip SIMD big-endian", std::vector(simd_be_vec.begin(), simd_be_vec.end()), simd_be_in);
1✔
191
         result.test_bin_eq("roundtrip SIMD array little-endian", simd_le_array_vec, simd_le_array_in);
1✔
192
         result.test_bin_eq("roundtrip SIMD array big-endian",
1✔
193
                            std::vector(simd_be_array_vec.begin(), simd_be_array_vec.end()),
1✔
194
                            simd_be_array_in);
195

196
         using StrongSIMD = Botan::Strong<Botan::SIMD_4x32, struct StrongSIMD_>;
1✔
197
         const auto simd_le_strong = Botan::load_le<StrongSIMD>(simd_le_in);
1✔
198
         const auto simd_be_strong = Botan::load_be<StrongSIMD>(simd_be_in);
1✔
199

200
         result.test_bin_eq(
1✔
201
            "roundtrip SIMD strong little-endian", Botan::store_le<std::vector<uint8_t>>(simd_le_strong), simd_le_in);
1✔
202
         result.test_bin_eq(
1✔
203
            "roundtrip SIMD strong big-endian", Botan::store_be<std::vector<uint8_t>>(simd_be_strong), simd_be_in);
1✔
204

205
         return {result};
2✔
206
      }
6✔
207

208
      static void BOTAN_FN_ISA_SIMD_4X32 test_eq(Test::Result& result,
31✔
209
                                                 const std::string& op,
210
                                                 const Botan::SIMD_4x32& simd,
211
                                                 uint32_t exp0,
212
                                                 uint32_t exp1,
213
                                                 uint32_t exp2,
214
                                                 uint32_t exp3) {
215
         uint8_t arr_be[16 + 15];
31✔
216
         uint8_t arr_be2[16 + 15];
31✔
217
         uint8_t arr_le[16 + 15];
31✔
218
         uint8_t arr_le2[16 + 15];
31✔
219

220
         for(size_t misalignment = 0; misalignment != 16; ++misalignment) {
527✔
221
            uint8_t* mem_be = arr_be + misalignment;
496✔
222
            uint8_t* mem_be2 = arr_be2 + misalignment;
496✔
223
            uint8_t* mem_le = arr_le + misalignment;
496✔
224
            uint8_t* mem_le2 = arr_le2 + misalignment;
496✔
225

226
            simd.store_be(mem_be);
496✔
227

228
            result.test_u32_eq(
992✔
229
               "SIMD_4x32 " + op + " elem0 BE", Botan::make_uint32(mem_be[0], mem_be[1], mem_be[2], mem_be[3]), exp0);
1,488✔
230
            result.test_u32_eq(
496✔
231
               "SIMD_4x32 " + op + " elem1 BE", Botan::make_uint32(mem_be[4], mem_be[5], mem_be[6], mem_be[7]), exp1);
1,488✔
232
            result.test_u32_eq(
496✔
233
               "SIMD_4x32 " + op + " elem2 BE", Botan::make_uint32(mem_be[8], mem_be[9], mem_be[10], mem_be[11]), exp2);
1,488✔
234
            result.test_u32_eq("SIMD_4x32 " + op + " elem3 BE",
992✔
235
                               Botan::make_uint32(mem_be[12], mem_be[13], mem_be[14], mem_be[15]),
496✔
236
                               exp3);
237

238
            // Check load_be+store_be results in same value
239
            const Botan::SIMD_4x32 reloaded_be = Botan::SIMD_4x32::load_be(mem_be);
496✔
240
            reloaded_be.store_be(mem_be2);
496✔
241
            result.test_bin_eq("SIMD_4x32 load_be", {mem_be, 16}, {mem_be2, 16});
496✔
242

243
            simd.store_le(mem_le);
496✔
244

245
            result.test_u32_eq(
992✔
246
               "SIMD_4x32 " + op + " elem0 LE", Botan::make_uint32(mem_le[3], mem_le[2], mem_le[1], mem_le[0]), exp0);
1,488✔
247
            result.test_u32_eq(
496✔
248
               "SIMD_4x32 " + op + " elem1 LE", Botan::make_uint32(mem_le[7], mem_le[6], mem_le[5], mem_le[4]), exp1);
1,488✔
249
            result.test_u32_eq(
496✔
250
               "SIMD_4x32 " + op + " elem2 LE", Botan::make_uint32(mem_le[11], mem_le[10], mem_le[9], mem_le[8]), exp2);
1,488✔
251
            result.test_u32_eq("SIMD_4x32 " + op + " elem3 LE",
992✔
252
                               Botan::make_uint32(mem_le[15], mem_le[14], mem_le[13], mem_le[12]),
496✔
253
                               exp3);
254

255
            // Check load_le+store_le results in same value
256
            const Botan::SIMD_4x32 reloaded_le = Botan::SIMD_4x32::load_le(mem_le);
496✔
257
            reloaded_le.store_le(mem_le2);
496✔
258
            result.test_bin_eq("SIMD_4x32 load_le", {mem_le, 16}, {mem_le2, 16});
496✔
259
         }
260
      }
31✔
261
};
262

263
BOTAN_REGISTER_TEST("utils", "simd_4x32", SIMD_4X32_Tests);
264
#endif
265

266
#if defined(BOTAN_HAS_SIMD_2X64) && defined(BOTAN_HAS_CPUID)
267

268
class SIMD_2X64_Tests final : public Test {
1✔
269
   public:
270
      std::vector<Test::Result> BOTAN_FN_ISA_SIMD_2X64 run() override {
1✔
271
         if(!Botan::CPUID::has(Botan::CPUID::Feature::SIMD_2X64)) {
1✔
272
            return {Test::Result::Note("simd_2x64", "Skipping tests due to missing SIMD support at runtime")};
×
273
         } else {
274
            return {test_simd_2x64()};
2✔
275
         }
276
      }
1✔
277

278
   private:
279
      Test::Result BOTAN_FN_ISA_SIMD_2X64 test_simd_2x64() {
1✔
280
         Test::Result result("SIMD_2x64");
1✔
281

282
         const uint64_t pat1 = 0x2F8C91D4A37E5C10;
1✔
283
         const uint64_t pat2 = 0x1B74A6F8C29D1345;
1✔
284

285
         const uint64_t pat1_1 = pat1 + pat1;
1✔
286
         const uint64_t pat1_2 = pat1 + pat2;
1✔
287

288
         test_eq(result, "default init", Botan::SIMD_2x64(), 0, 0);
1✔
289
         test_eq(result, "SIMD scalar constructor", Botan::SIMD_2x64(1, 2), 1, 2);
1✔
290

291
         const auto input = Botan::SIMD_2x64(pat1, pat2);
1✔
292
         const auto splat = Botan::SIMD_2x64(pat1, pat1);
1✔
293

294
         const auto rotl = input.rotl<3>();
1✔
295
         test_eq(result, "rotl", rotl, Botan::rotl<3>(pat1), Botan::rotl<3>(pat2));
1✔
296

297
         const auto rotr = input.rotr<9>();
1✔
298
         test_eq(result, "rotr", rotr, Botan::rotr<9>(pat1), Botan::rotr<9>(pat2));
1✔
299

300
         test_eq(result, "rotr<8>", input.rotr<8>(), Botan::rotr<8>(pat1), Botan::rotr<8>(pat2));
1✔
301
         test_eq(result, "rotr<16>", input.rotr<16>(), Botan::rotr<16>(pat1), Botan::rotr<16>(pat2));
1✔
302
         test_eq(result, "rotr<24>", input.rotr<24>(), Botan::rotr<24>(pat1), Botan::rotr<24>(pat2));
1✔
303
         test_eq(result, "rotr<32>", input.rotr<32>(), Botan::rotr<32>(pat1), Botan::rotr<32>(pat2));
1✔
304

305
         const auto add = input + splat;
1✔
306
         test_eq(result, "add +", add, pat1_1, pat1_2);
1✔
307

308
         test_eq(result, "xor", input ^ splat, 0, pat2 ^ pat1);
1✔
309

310
         auto shifter = Botan::SIMD_2x64(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF);
1✔
311
         shifter = shifter.shr<23>();
1✔
312
         test_eq(result, ">>", shifter, 0x1FFFFFFFFFF, 0x1FFFFFFFFFF);
1✔
313

314
         shifter = shifter.shl<27>();
1✔
315
         test_eq(result, "<<", shifter, 0xFFFFFFFFF8000000, 0xFFFFFFFFF8000000);
1✔
316

317
         shifter = input.andc(shifter);
1✔
318
         test_eq(result, "andc", shifter, ~pat1 & 0xFFFFFFFFF8000000, ~pat2 & 0xFFFFFFFFF8000000);
1✔
319

320
         test_eq(result, "bswap", input.bswap(), Botan::reverse_bytes(pat1), Botan::reverse_bytes(pat2));
1✔
321

322
         test_eq(result,
1✔
323
                 "reverse_all_bytes",
324
                 Botan::SIMD_2x64(0x0001020304050607, 0x08090a0b0c0d0e0f).reverse_all_bytes(),
1✔
325
                 0x0f0e0d0c0b0a0908,
326
                 0x0706050403020100);
327

328
         test_eq(result, "swap_lanes", Botan::SIMD_2x64(pat1, pat2).swap_lanes(), pat2, pat1);
1✔
329

330
         const auto interleave_a = Botan::SIMD_2x64(0x1111111122222222, 0x3333333344444444);
1✔
331
         const auto interleave_b = Botan::SIMD_2x64(0x5555555566666666, 0x7777777788888888);
1✔
332
         test_eq(result,
1✔
333
                 "interleave_high",
334
                 Botan::SIMD_2x64::interleave_high(interleave_a, interleave_b),
1✔
335
                 0x3333333344444444,
336
                 0x7777777788888888);
337

338
         test_eq(result,
1✔
339
                 "interleave_low",
340
                 Botan::SIMD_2x64::interleave_low(interleave_a, interleave_b),
1✔
341
                 0x1111111122222222,
342
                 0x5555555566666666);
343

344
         test_eq(result, "all_ones", Botan::SIMD_2x64::all_ones(), 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF);
1✔
345

346
         // Test load/stores SIMD wrapper types
347
         const auto simd_le_in = Botan::hex_decode("ABCDEF01234567890123456789ABCDEF");
1✔
348
         const auto simd_be_in = Botan::hex_decode("0123456789ABCDEFABCDEF0123456789");
1✔
349
         const auto simd_le_array_in = Botan::concat(simd_le_in, simd_be_in);
1✔
350
         const auto simd_be_array_in = Botan::concat(simd_be_in, simd_le_in);
1✔
351

352
         auto simd_le = Botan::load_le<Botan::SIMD_2x64>(simd_le_in);
1✔
353
         auto simd_be = Botan::load_be<Botan::SIMD_2x64>(simd_be_in);
1✔
354
         auto simd_le_array = Botan::load_le<std::array<Botan::SIMD_2x64, 2>>(simd_le_array_in);
1✔
355
         auto simd_be_array = Botan::load_be<std::array<Botan::SIMD_2x64, 2>>(simd_be_array_in);
1✔
356

357
         auto simd_le_vec = Botan::store_le<std::vector<uint8_t>>(simd_le);
1✔
358
         auto simd_be_vec = Botan::store_be(simd_be);
1✔
359
         auto simd_le_array_vec = Botan::store_le<std::vector<uint8_t>>(simd_le_array);
1✔
360
         auto simd_be_array_vec = Botan::store_be(simd_be_array);
1✔
361

362
         result.test_bin_eq("roundtrip SIMD little-endian", simd_le_vec, simd_le_in);
1✔
363
         result.test_bin_eq(
1✔
364
            "roundtrip SIMD big-endian", std::vector(simd_be_vec.begin(), simd_be_vec.end()), simd_be_in);
1✔
365
         result.test_bin_eq("roundtrip SIMD array little-endian", simd_le_array_vec, simd_le_array_in);
1✔
366
         result.test_bin_eq("roundtrip SIMD array big-endian",
1✔
367
                            std::vector(simd_be_array_vec.begin(), simd_be_array_vec.end()),
1✔
368
                            simd_be_array_in);
369

370
         using StrongSIMD = Botan::Strong<Botan::SIMD_2x64, struct StrongSIMD_>;
1✔
371
         const auto simd_le_strong = Botan::load_le<StrongSIMD>(simd_le_in);
1✔
372
         const auto simd_be_strong = Botan::load_be<StrongSIMD>(simd_be_in);
1✔
373

374
         result.test_bin_eq(
1✔
375
            "roundtrip SIMD strong little-endian", Botan::store_le<std::vector<uint8_t>>(simd_le_strong), simd_le_in);
1✔
376
         result.test_bin_eq(
1✔
377
            "roundtrip SIMD strong big-endian", Botan::store_be<std::vector<uint8_t>>(simd_be_strong), simd_be_in);
1✔
378

379
         return {result};
2✔
380
      }
6✔
381

382
   private:
383
      static void BOTAN_FN_ISA_SIMD_2X64
384
      test_eq(Test::Result& result, const std::string& op, const Botan::SIMD_2x64& simd, uint64_t exp0, uint64_t exp1) {
19✔
385
         uint8_t arr_be[16 + 15];
19✔
386
         uint8_t arr_be2[16 + 15];
19✔
387
         uint8_t arr_le[16 + 15];
19✔
388
         uint8_t arr_le2[16 + 15];
19✔
389

390
         for(size_t misalignment = 0; misalignment != 16; ++misalignment) {
323✔
391
            uint8_t* mem_be = arr_be + misalignment;
304✔
392
            uint8_t* mem_be2 = arr_be2 + misalignment;
304✔
393
            uint8_t* mem_le = arr_le + misalignment;
304✔
394
            uint8_t* mem_le2 = arr_le2 + misalignment;
304✔
395

396
            simd.store_be(mem_be);
304✔
397

398
            result.test_u64_eq(
608✔
399
               "SIMD_2x64 " + op + " elem0 BE",
912✔
400
               Botan::make_uint64(
401
                  mem_be[0], mem_be[1], mem_be[2], mem_be[3], mem_be[4], mem_be[5], mem_be[6], mem_be[7]),
402
               exp0);
403
            result.test_u64_eq(
304✔
404
               "SIMD_2x64 " + op + " elem1 BE",
912✔
405
               Botan::make_uint64(
406
                  mem_be[8], mem_be[9], mem_be[10], mem_be[11], mem_be[12], mem_be[13], mem_be[14], mem_be[15]),
304✔
407
               exp1);
408

409
            // Check load_be+store_be results in same value
410
            const Botan::SIMD_2x64 reloaded_be = Botan::SIMD_2x64::load_be(mem_be);
304✔
411
            reloaded_be.store_be(mem_be2);
304✔
412
            result.test_bin_eq("SIMD_2x64 load_be", {mem_be, 16}, {mem_be2, 16});
304✔
413

414
            simd.store_le(mem_le);
304✔
415

416
            result.test_u64_eq(
608✔
417
               "SIMD_2x64 " + op + " elem0 LE",
912✔
418
               Botan::make_uint64(
419
                  mem_le[7], mem_le[6], mem_le[5], mem_le[4], mem_le[3], mem_le[2], mem_le[1], mem_le[0]),
420
               exp0);
421
            result.test_u64_eq(
304✔
422
               "SIMD_2x64 " + op + " elem1 LE",
912✔
423
               Botan::make_uint64(
424
                  mem_le[15], mem_le[14], mem_le[13], mem_le[12], mem_le[11], mem_le[10], mem_le[9], mem_le[8]),
304✔
425
               exp1);
426

427
            // Check load_le+store_le results in same value
428
            const Botan::SIMD_2x64 reloaded_le = Botan::SIMD_2x64::load_le(mem_le);
304✔
429
            reloaded_le.store_le(mem_le2);
304✔
430
            result.test_bin_eq("SIMD_2x64 load_le", {mem_le, 16}, {mem_le2, 16});
304✔
431
         }
432
      }
19✔
433
};
434

435
BOTAN_REGISTER_TEST("utils", "simd_2x64", SIMD_2X64_Tests);
436
#endif
437

438
#if defined(BOTAN_HAS_SIMD_8X32) && defined(BOTAN_HAS_CPUID)
439

440
class SIMD_8X32_Tests final : public Test {
1✔
441
   public:
442
      std::vector<Test::Result> run() override {
1✔
443
         if(!Botan::CPUID::has(Botan::CPUID::Feature::SIMD_8X32)) {
1✔
444
            return {Test::Result::Note("simd_8x32", "Skipping tests due to missing SIMD support at runtime")};
×
445
         } else {
446
            return {test_simd_8x32()};
2✔
447
         }
448
      }
1✔
449

450
   private:
451
      using W8 = std::array<uint32_t, 8>;
452

453
      Test::Result BOTAN_FN_ISA_SIMD_8X32 test_simd_8x32() {
1✔
454
         Test::Result result("SIMD_8x32");
1✔
455

456
         const W8 pat = {
1✔
457
            0xAABBCCDD, 0x87654321, 0x01234567, 0xC0D0E0F0, 0x13579BDF, 0x2468ACE0, 0xFEDCBA98, 0x76543210};
458

459
         test_eq(result, "default init", Botan::SIMD_8x32(), W8{0, 0, 0, 0, 0, 0, 0, 0});
1✔
460
         test_eq(result, "scalar constructor", Botan::SIMD_8x32(1, 2, 3, 4, 5, 6, 7, 8), W8{1, 2, 3, 4, 5, 6, 7, 8});
1✔
461
         test_eq(result, "4 word constructor", Botan::SIMD_8x32(1, 2, 3, 4), W8{1, 2, 3, 4, 1, 2, 3, 4});
1✔
462
         test_eq(result, "array constructor", Botan::SIMD_8x32(pat.data()), pat);
1✔
463
         test_eq(result, "splat", Botan::SIMD_8x32::splat(pat[0]), splat8(pat[0]));
1✔
464

465
         const Botan::SIMD_8x32 input(pat.data());
1✔
466
         const Botan::SIMD_8x32 splat = Botan::SIMD_8x32::splat(pat[0]);
1✔
467

468
         test_eq(result, "rotl<3>", input.rotl<3>(), map(pat, [](uint32_t x) { return Botan::rotl<3>(x); }));
1✔
469
         test_eq(result, "rotl<8>", input.rotl<8>(), map(pat, [](uint32_t x) { return Botan::rotl<8>(x); }));
1✔
470
         test_eq(result, "rotl<16>", input.rotl<16>(), map(pat, [](uint32_t x) { return Botan::rotl<16>(x); }));
1✔
471
         test_eq(result, "rotl<24>", input.rotl<24>(), map(pat, [](uint32_t x) { return Botan::rotl<24>(x); }));
1✔
472
         test_eq(result, "rotr<9>", input.rotr<9>(), map(pat, [](uint32_t x) { return Botan::rotr<9>(x); }));
1✔
473

474
         test_eq(result, "sigma0", input.sigma0(), map(pat, [](uint32_t x) {
1✔
475
                    return Botan::rotr<2>(x) ^ Botan::rotr<13>(x) ^ Botan::rotr<22>(x);
8✔
476
                 }));
477
         test_eq(result, "sigma1", input.sigma1(), map(pat, [](uint32_t x) {
1✔
478
                    return Botan::rotr<6>(x) ^ Botan::rotr<11>(x) ^ Botan::rotr<25>(x);
8✔
479
                 }));
480

481
         test_eq(
1✔
482
            result, "add +", input + splat, zip(pat, splat8(pat[0]), [](uint32_t x, uint32_t y) { return x + y; }));
1✔
483
         test_eq(
1✔
484
            result, "sub -", input - splat, zip(pat, splat8(pat[0]), [](uint32_t x, uint32_t y) { return x - y; }));
1✔
485
         test_eq(result, "xor", input ^ splat, zip(pat, splat8(pat[0]), [](uint32_t x, uint32_t y) { return x ^ y; }));
1✔
486
         test_eq(result, "or", input | splat, zip(pat, splat8(pat[0]), [](uint32_t x, uint32_t y) { return x | y; }));
1✔
487
         test_eq(result, "and", input & splat, zip(pat, splat8(pat[0]), [](uint32_t x, uint32_t y) { return x & y; }));
1✔
488

489
         Botan::SIMD_8x32 acc = input;
1✔
490
         acc += splat;
1✔
491
         test_eq(result, "+=", acc, zip(pat, splat8(pat[0]), [](uint32_t x, uint32_t y) { return x + y; }));
1✔
492
         acc -= splat;
1✔
493
         test_eq(result, "-=", acc, pat);
1✔
494
         acc |= splat;
1✔
495
         test_eq(result, "|=", acc, zip(pat, splat8(pat[0]), [](uint32_t x, uint32_t y) { return x | y; }));
1✔
496
         acc &= splat;
1✔
497
         test_eq(result, "&=", acc, splat8(pat[0]));
1✔
498
         acc ^= splat;
1✔
499
         test_eq(result, "^=", acc, W8{0, 0, 0, 0, 0, 0, 0, 0});
1✔
500
         acc ^= pat[1];
1✔
501
         test_eq(result, "^= u32", acc, splat8(pat[1]));
1✔
502

503
         test_eq(result, "~", ~input, map(pat, [](uint32_t x) { return ~x; }));
1✔
504
         test_eq(result, "shl<5>", input.shl<5>(), map(pat, [](uint32_t x) { return x << 5; }));
1✔
505
         test_eq(result, "shr<7>", input.shr<7>(), map(pat, [](uint32_t x) { return x >> 7; }));
1✔
506
         test_eq(
1✔
507
            result, "andc", input.andc(splat), zip(pat, splat8(pat[0]), [](uint32_t x, uint32_t y) { return ~x & y; }));
1✔
508

509
         test_eq(result, "bswap", input.bswap(), map(pat, [](uint32_t x) { return Botan::reverse_bytes(x); }));
1✔
510
         test_eq(
1✔
511
            result, "rev_words", input.rev_words(), W8{pat[3], pat[2], pat[1], pat[0], pat[7], pat[6], pat[5], pat[4]});
1✔
512
         test_eq(result, "reverse", input.reverse(), input.rev_words().bswap());
2✔
513

514
         const auto lo_mask = Botan::SIMD_8x32(0xFFFFFFFF, 0, 0xFFFFFFFF, 0, 0, 0xFFFFFFFF, 0, 0xFFFFFFFF);
1✔
515
         test_eq(result,
1✔
516
                 "choose",
517
                 Botan::SIMD_8x32::choose(lo_mask, input, splat),
1✔
518
                 W8{pat[0], pat[0], pat[2], pat[0], pat[0], pat[5], pat[0], pat[7]});
1✔
519

520
         const auto maj_x =
1✔
521
            Botan::SIMD_8x32(0xF0F0F0F0, 0x00000000, 0xFFFFFFFF, 0x12345678, 0xF0F0F0F0, 0, 0xFFFFFFFF, 0x12345678);
1✔
522
         const auto maj_y = Botan::SIMD_8x32(
1✔
523
            0xFF00FF00, 0xFFFFFFFF, 0xFFFFFFFF, 0x0F0F0F0F, 0xFF00FF00, 0xFFFFFFFF, 0xFFFFFFFF, 0x0F0F0F0F);
1✔
524
         const auto maj_z =
1✔
525
            Botan::SIMD_8x32(0xAAAAAAAA, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xAAAAAAAA, 0, 0, 0xFFFFFFFF);
1✔
526
         test_eq(result,
1✔
527
                 "majority",
528
                 Botan::SIMD_8x32::majority(maj_x, maj_y, maj_z),
1✔
529
                 W8{(0xF0F0F0F0 & 0xFF00FF00) | (0xF0F0F0F0 & 0xAAAAAAAA) | (0xFF00FF00 & 0xAAAAAAAA),
1✔
530
                    0,
531
                    0xFFFFFFFF,
532
                    (0x12345678 & 0x0F0F0F0F) | (0x12345678 & 0xFFFFFFFF) | (0x0F0F0F0F & 0xFFFFFFFF),
533
                    (0xF0F0F0F0 & 0xFF00FF00) | (0xF0F0F0F0 & 0xAAAAAAAA) | (0xFF00FF00 & 0xAAAAAAAA),
534
                    0,
535
                    0xFFFFFFFF,
536
                    (0x12345678 & 0x0F0F0F0F) | (0x12345678 & 0xFFFFFFFF) | (0x0F0F0F0F & 0xFFFFFFFF)});
537

538
         const auto ult_a = Botan::SIMD_8x32(0, 1, 0x80000000, 0xFFFFFFFF, 5, 0x7FFFFFFF, 0x80000001, 0x80000000);
1✔
539
         const auto ult_b = Botan::SIMD_8x32(1, 0, 0x7FFFFFFF, 0xFFFFFFFF, 5, 0x80000000, 0x80000000, 0x80000001);
1✔
540
         test_eq(
1✔
541
            result, "unsigned_lt", ult_a.unsigned_lt(ult_b), W8{0xFFFFFFFF, 0, 0, 0, 0, 0xFFFFFFFF, 0, 0xFFFFFFFF});
1✔
542

543
         test_eq(result,
1✔
544
                 "shift_elems_left<1>",
545
                 input.shift_elems_left<1>(),
1✔
546
                 W8{0, pat[0], pat[1], pat[2], 0, pat[4], pat[5], pat[6]});
1✔
547
         test_eq(
1✔
548
            result, "shift_elems_left<2>", input.shift_elems_left<2>(), W8{0, 0, pat[0], pat[1], 0, 0, pat[4], pat[5]});
1✔
549
         test_eq(result, "shift_elems_left<3>", input.shift_elems_left<3>(), W8{0, 0, 0, pat[0], 0, 0, 0, pat[4]});
1✔
550
         test_eq(result,
1✔
551
                 "shift_elems_right<1>",
552
                 input.shift_elems_right<1>(),
1✔
553
                 W8{pat[1], pat[2], pat[3], 0, pat[5], pat[6], pat[7], 0});
1✔
554
         test_eq(result,
1✔
555
                 "shift_elems_right<2>",
556
                 input.shift_elems_right<2>(),
1✔
557
                 W8{pat[2], pat[3], 0, 0, pat[6], pat[7], 0, 0});
1✔
558
         test_eq(result, "shift_elems_right<3>", input.shift_elems_right<3>(), W8{pat[3], 0, 0, 0, pat[7], 0, 0, 0});
1✔
559

560
         const Botan::SIMD_8x32 other(11, 12, 13, 14, 15, 16, 17, 18);
1✔
561
         test_eq(result,
1✔
562
                 "alignr8",
563
                 Botan::SIMD_8x32::alignr8(other, input),
1✔
564
                 W8{pat[2], pat[3], 11, 12, pat[6], pat[7], 15, 16});
1✔
565

566
         // Byte shuffle within each lane: reverse the byte order of each 32-bit word (ie bswap)
567
         const Botan::SIMD_8x32 bswap_idx(0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F);
1✔
568
         test_eq(result, "byte_shuffle bswap", Botan::SIMD_8x32::byte_shuffle(input, bswap_idx), input.bswap());
2✔
569
         // Byte shuffle within each lane: reverse the byte order of the whole lane
570
         const Botan::SIMD_8x32 rev_idx(0x0C0D0E0F, 0x08090A0B, 0x04050607, 0x00010203);
1✔
571
         test_eq(result, "byte_shuffle reverse", Botan::SIMD_8x32::byte_shuffle(input, rev_idx), input.reverse());
2✔
572
         // Broadcast the first word of each lane
573
         const Botan::SIMD_8x32 splat_idx(0x03020100, 0x03020100, 0x03020100, 0x03020100);
1✔
574
         test_eq(result,
1✔
575
                 "byte_shuffle splat",
576
                 Botan::SIMD_8x32::byte_shuffle(input, splat_idx),
1✔
577
                 W8{pat[0], pat[0], pat[0], pat[0], pat[4], pat[4], pat[4], pat[4]});
1✔
578

579
         test_eq(result,
1✔
580
                 "swap_halves",
581
                 input.swap_halves(),
1✔
582
                 W8{pat[4], pat[5], pat[6], pat[7], pat[0], pat[1], pat[2], pat[3]});
1✔
583

584
         // Masked shuffle: reverse the bytes of the first word of each half, zero the rest
585
         const Botan::SIMD_8x32 mrev_idx(0x00010203, 0xFFFFFFFF, 0x80808080, 0xFFFFFFFF);
1✔
586
         test_eq(result,
1✔
587
                 "masked_byte_shuffle",
588
                 Botan::SIMD_8x32::masked_byte_shuffle(input, mrev_idx),
1✔
589
                 W8{Botan::reverse_bytes(pat[0]), 0, 0, 0, Botan::reverse_bytes(pat[4]), 0, 0, 0});
1✔
590
         // Bits 4-6 of an index are ignored, unless the top bit is set
591
         const Botan::SIMD_8x32 mzero_idx(0x73727170, 0x0F0E0D0C, 0xC7C6C5C4, 0x0B0A0908);
1✔
592
         test_eq(result,
1✔
593
                 "masked_byte_shuffle high bits",
594
                 Botan::SIMD_8x32::masked_byte_shuffle(input, mzero_idx),
1✔
595
                 W8{pat[0], pat[3], 0, pat[2], pat[4], pat[7], 0, pat[6]});
1✔
596

597
         // Load xtime input at runtime, otherwise MSVC performs in incorrect constant folding
598
         const auto xt_bytes = Botan::hex_decode("1020408001020408C0007FFFEC763B1D1020408001020408C0007FFFEC763B1D");
1✔
599
         const auto xt_in = Botan::SIMD_8x32::load_le(xt_bytes.data());
1✔
600
         test_eq(result,
1✔
601
                 "xtime<0x1D>",
602
                 xt_in.xtime<0x1D>(),
1✔
603
                 W8{0x1D804020, 0x10080402, 0xE3FE009D, 0x3A76ECC5, 0x1D804020, 0x10080402, 0xE3FE009D, 0x3A76ECC5});
1✔
604
         test_eq(result,
1✔
605
                 "xtime<0x1B>",
606
                 xt_in.xtime<0x1B>(),
1✔
607
                 W8{0x1B804020, 0x10080402, 0xE5FE009B, 0x3A76ECC3, 0x1B804020, 0x10080402, 0xE5FE009B, 0x3A76ECC3});
1✔
608

609
         Botan::SIMD_8x32 t0(pat[0], pat[1], pat[2], pat[3], pat[4], pat[5], pat[6], pat[7]);
1✔
610
         Botan::SIMD_8x32 t1(
1✔
611
            pat[0] + 1, pat[1] + 1, pat[2] + 1, pat[3] + 1, pat[4] + 1, pat[5] + 1, pat[6] + 1, pat[7] + 1);
1✔
612
         Botan::SIMD_8x32 t2(
1✔
613
            pat[0] + 2, pat[1] + 2, pat[2] + 2, pat[3] + 2, pat[4] + 2, pat[5] + 2, pat[6] + 2, pat[7] + 2);
1✔
614
         Botan::SIMD_8x32 t3(
1✔
615
            pat[0] + 3, pat[1] + 3, pat[2] + 3, pat[3] + 3, pat[4] + 3, pat[5] + 3, pat[6] + 3, pat[7] + 3);
1✔
616

617
         Botan::SIMD_8x32::transpose(t0, t1, t2, t3);
1✔
618

619
         test_eq(result,
1✔
620
                 "transpose4 t0",
621
                 t0,
622
                 W8{pat[0], pat[0] + 1, pat[0] + 2, pat[0] + 3, pat[4], pat[4] + 1, pat[4] + 2, pat[4] + 3});
1✔
623
         test_eq(result,
1✔
624
                 "transpose4 t1",
625
                 t1,
626
                 W8{pat[1], pat[1] + 1, pat[1] + 2, pat[1] + 3, pat[5], pat[5] + 1, pat[5] + 2, pat[5] + 3});
1✔
627
         test_eq(result,
1✔
628
                 "transpose4 t2",
629
                 t2,
630
                 W8{pat[2], pat[2] + 1, pat[2] + 2, pat[2] + 3, pat[6], pat[6] + 1, pat[6] + 2, pat[6] + 3});
1✔
631
         test_eq(result,
1✔
632
                 "transpose4 t3",
633
                 t3,
634
                 W8{pat[3], pat[3] + 1, pat[3] + 2, pat[3] + 3, pat[7], pat[7] + 1, pat[7] + 2, pat[7] + 3});
1✔
635

636
         // Fill 8 registers with r*8+c and check that the 8x8 transpose gives c*8+r
637
         Botan::SIMD_8x32 m[8];
9✔
638
         for(uint32_t r = 0; r != 8; ++r) {
9✔
639
            m[r] = Botan::SIMD_8x32(r * 8, r * 8 + 1, r * 8 + 2, r * 8 + 3, r * 8 + 4, r * 8 + 5, r * 8 + 6, r * 8 + 7);
8✔
640
         }
641
         Botan::SIMD_8x32::transpose(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7]);
1✔
642
         for(uint32_t c = 0; c != 8; ++c) {
9✔
643
            test_eq(result, "transpose8", m[c], W8{c, 8 + c, 16 + c, 24 + c, 32 + c, 40 + c, 48 + c, 56 + c});
16✔
644
         }
645

646
         // Load/store variants
647
         const auto in32 = Botan::hex_decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
1✔
648
         const auto le = Botan::SIMD_8x32::load_le(in32.data());
1✔
649
         test_eq(result,
1✔
650
                 "load_le",
651
                 le,
652
                 W8{0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C, 0x13121110, 0x17161514, 0x1B1A1918, 0x1F1E1D1C});
1✔
653
         const auto be = Botan::SIMD_8x32::load_be(in32.data());
1✔
654
         test_eq(result,
1✔
655
                 "load_be",
656
                 be,
657
                 W8{0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F, 0x10111213, 0x14151617, 0x18191A1B, 0x1C1D1E1F});
1✔
658

659
         const auto b128 = Botan::SIMD_8x32::load_le128(in32.data());
1✔
660
         test_eq(result,
1✔
661
                 "load_le128 broadcast",
662
                 b128,
663
                 W8{0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C, 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C});
1✔
664
         const auto b128w = Botan::SIMD_8x32::load_le128(reinterpret_cast<const uint32_t*>(in32.data()));
1✔
665
         test_eq(result,
1✔
666
                 "load_le128 broadcast u32",
667
                 b128w,
668
                 W8{0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C, 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C});
1✔
669

670
         // NOLINTBEGIN(*-container-data-pointer)
671
         const auto le2 = Botan::SIMD_8x32::load_le128(reinterpret_cast<const uint32_t*>(&in32[16]),
1✔
672
                                                       reinterpret_cast<const uint32_t*>(&in32[0]));
1✔
673
         test_eq(result,
1✔
674
                 "load_le128 two u32 ptrs",
675
                 le2,
676
                 W8{0x13121110, 0x17161514, 0x1B1A1918, 0x1F1E1D1C, 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C});
1✔
677
         const auto be2 = Botan::SIMD_8x32::load_be128(&in32[16], &in32[0]);
1✔
678
         test_eq(result,
1✔
679
                 "load_be128 two ptrs",
680
                 be2,
681
                 W8{0x10111213, 0x14151617, 0x18191A1B, 0x1C1D1E1F, 0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F});
1✔
682

683
         uint8_t out16[16];
1✔
684
         le2.store_le128(out16);
1✔
685
         result.test_bin_eq(
1✔
686
            "store_le128 low", std::span<const uint8_t>(out16), std::span<const uint8_t>(&in32[16], 16));
1✔
687

688
         uint32_t out32a[4];
1✔
689
         uint32_t out32b[4];
1✔
690
         le2.store_le128(out32a, out32b);
1✔
691
         result.test_bin_eq("store_le128 two u32 ptrs (low)",
1✔
692
                            std::span<const uint8_t>(reinterpret_cast<const uint8_t*>(out32a), 16),
693
                            std::span<const uint8_t>(&in32[16], 16));
1✔
694
         result.test_bin_eq("store_le128 two u32 ptrs (high)",
1✔
695
                            std::span<const uint8_t>(reinterpret_cast<const uint8_t*>(out32b), 16),
696
                            std::span<const uint8_t>(&in32[0], 16));
1✔
697
         // NOLINTEND(*-container-data-pointer)
698

699
         return result;
1✔
700
      }
2✔
701

702
      static W8 splat8(uint32_t x) { return W8{x, x, x, x, x, x, x, x}; }
3✔
703

704
      template <typename F>
705
      static W8 map(const W8& a, F f) {
11✔
706
         W8 r{};
11✔
707
         for(size_t i = 0; i != 8; ++i) {
99✔
708
            r[i] = f(a[i]);
88✔
709
         }
710
         return r;
711
      }
712

713
      template <typename F>
714
      static W8 zip(const W8& a, const W8& b, F f) {
8✔
715
         W8 r{};
8✔
716
         for(size_t i = 0; i != 8; ++i) {
72✔
717
            r[i] = f(a[i], b[i]);
64✔
718
         }
719
         return r;
720
      }
721

722
      static void BOTAN_FN_ISA_SIMD_8X32 test_eq(Test::Result& result,
3✔
723
                                                 const std::string& op,
724
                                                 const Botan::SIMD_8x32& simd,
725
                                                 const Botan::SIMD_8x32& expected) {
726
         W8 exp{};
3✔
727
         expected.store_le(exp.data());
3✔
728
         test_eq(result, op, simd, exp);
3✔
729
      }
730

731
      static void BOTAN_FN_ISA_SIMD_8X32 test_eq(Test::Result& result,
66✔
732
                                                 const std::string& op,
733
                                                 const Botan::SIMD_8x32& simd,
734
                                                 const W8& expected) {
735
         uint8_t arr_be[32 + 31];
66✔
736
         uint8_t arr_be2[32 + 31];
66✔
737
         uint8_t arr_le[32 + 31];
66✔
738
         uint8_t arr_le2[32 + 31];
66✔
739

740
         for(size_t misalignment = 0; misalignment < 32; misalignment += 5) {
528✔
741
            uint8_t* mem_be = arr_be + misalignment;
462✔
742
            uint8_t* mem_be2 = arr_be2 + misalignment;
462✔
743
            uint8_t* mem_le = arr_le + misalignment;
462✔
744
            uint8_t* mem_le2 = arr_le2 + misalignment;
462✔
745

746
            simd.store_be(mem_be);
462✔
747
            simd.store_le(mem_le);
462✔
748

749
            for(size_t i = 0; i != 8; ++i) {
4,158✔
750
               result.test_u32_eq("SIMD_8x32 " + op + " elem" + std::to_string(i) + " BE",
14,784✔
751
                                  Botan::load_be<uint32_t>(mem_be, i),
752
                                  expected[i]);
3,696✔
753
               result.test_u32_eq("SIMD_8x32 " + op + " elem" + std::to_string(i) + " LE",
14,784✔
754
                                  Botan::load_le<uint32_t>(mem_le, i),
755
                                  expected[i]);
3,696✔
756
            }
757

758
            // Check load_be+store_be results in same value
759
            Botan::SIMD_8x32::load_be(mem_be).store_be(mem_be2);
462✔
760
            result.test_bin_eq("SIMD_8x32 load_be", {mem_be, 32}, {mem_be2, 32});
462✔
761

762
            // Check load_le+store_le results in same value
763
            Botan::SIMD_8x32::load_le(mem_le).store_le(mem_le2);
462✔
764
            result.test_bin_eq("SIMD_8x32 load_le", {mem_le, 32}, {mem_le2, 32});
462✔
765
         }
766

767
         // Also check the uint32_t store overload
768
         W8 words{};
66✔
769
         simd.store_le(words.data());
66✔
770
         result.test_is_true("SIMD_8x32 " + op + " store_le u32", words == expected);
198✔
771
      }
66✔
772
};
773

774
BOTAN_REGISTER_TEST("utils", "simd_8x32", SIMD_8X32_Tests);
775
#endif
776

777
}  // namespace
778

779
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc