1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2018 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "qendian.h"
42
43#include "qalgorithms.h"
44#include <private/qsimd_p.h>
45
46QT_BEGIN_NAMESPACE
47
48/*!
49 \headerfile <QtEndian>
50 \title Endian Conversion Functions
51 \ingroup funclists
52 \brief The <QtEndian> header provides functions to convert between
53 little and big endian representations of numbers.
54*/
55
56/*!
57 \fn template <typename T> T qFromUnaligned(const void *ptr)
58 \internal
59 \since 5.5
60
61 Loads a \c{T} from address \a ptr, which may be misaligned.
62
63 Use of this function avoids the undefined behavior that the C++ standard
64 otherwise attributes to unaligned loads.
65*/
66
67/*!
68 \fn template <typename T> void qToUnaligned(const T t, void *ptr)
69 \internal
70 \since 4.5
71
72 Stores \a t to address \a ptr, which may be misaligned.
73
74 Use of this function avoids the undefined behavior that the C++ standard
75 otherwise attributes to unaligned stores.
76*/
77
78
79/*!
80 \fn template <typename T> T qFromBigEndian(const void *src)
81 \since 4.3
82 \relates <QtEndian>
83
84 Reads a big-endian number from memory location \a src and returns the number in the
85 host byte order representation.
86 On CPU architectures where the host byte order is little-endian (such as x86) this
87 will swap the byte order; otherwise it will just read from \a src.
88
89 \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
90 quint64, or qint64. Other types of integers, e.g., qlong, are not
91 applicable.
92
93 \note Since Qt 5.7, the type of the \a src parameter is a void pointer.
94
95 There are no data alignment constraints for \a src.
96
97 \sa qFromLittleEndian()
98 \sa qToBigEndian()
99 \sa qToLittleEndian()
100*/
101/*!
102 \fn template <typename T> T qFromBigEndian(T src)
103 \since 4.3
104 \relates <QtEndian>
105 \overload
106
107 Converts \a src from big-endian byte order and returns the number in host byte order
108 representation of that number.
109 On CPU architectures where the host byte order is little-endian (such as x86) this
110 will return \a src with the byte order swapped; otherwise it will return \a src
111 unmodified.
112*/
113/*!
114 \fn template <typename T> T qFromBigEndian(const void *src, qsizetype count, void *dest)
115 \since 5.12
116 \relates <QtEndian>
117
118 Reads \a count big-endian numbers from memory location \a src and stores
119 them in the host byte order representation at \a dest. On CPU architectures
120 where the host byte order is little-endian (such as x86) this will swap the
121 byte order; otherwise it will just perform a \c memcpy from \a src to \a
122 dest.
123
124 \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
125 quint64, or qint64. Other types of integers, e.g., qlong, are not
126 applicable.
127
128 There are no data alignment constraints for \a src. However, \a dest is
129 expected to be naturally aligned for type \c{T}.
130
131 If \a src and \a dest can be the same pointer, this function will perform
132 an in-place swap (if necessary). If they are not the same, the memory
133 regions must not overlap.
134
135 \sa qFromLittleEndian()
136 \sa qToBigEndian()
137 \sa qToLittleEndian()
138*/
139/*!
140 \fn template <typename T> inline T qFromLittleEndian(const void *src)
141 \since 4.3
142 \relates <QtEndian>
143
144 Reads a little-endian number from memory location \a src and returns the number in
145 the host byte order representation.
146 On CPU architectures where the host byte order is big-endian (such as PowerPC) this
147 will swap the byte order; otherwise it will just read from \a src.
148
149 \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
150 quint64, or qint64. Other types of integers, e.g., qlong, are not
151 applicable.
152
153 \note Since Qt 5.7, the type of the \a src parameter is a void pointer.
154
155 There are no data alignment constraints for \a src.
156
157 \sa qFromBigEndian()
158 \sa qToBigEndian()
159 \sa qToLittleEndian()
160*/
161/*!
162 \fn template <typename T> inline T qFromLittleEndian(T src)
163 \since 4.3
164 \relates <QtEndian>
165 \overload
166
167 Converts \a src from little-endian byte order and returns the number in host byte
168 order representation of that number.
169 On CPU architectures where the host byte order is big-endian (such as PowerPC) this
170 will return \a src with the byte order swapped; otherwise it will return \a src
171 unmodified.
172*/
173/*!
174 \fn template <typename T> inline T qFromLittleEndian(const void *src, qsizetype count, void *dest)
175 \since 5.12
176 \relates <QtEndian>
177
178 Reads \a count little-endian numbers from memory location \a src and stores
179 them in the host byte order representation at \a dest. On CPU architectures
180 where the host byte order is big-endian (such as PowerPC) this will swap the
181 byte order; otherwise it will just perform a \c memcpy from \a src to \a
182 dest.
183
184 \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
185 quint64, or qint64. Other types of integers, e.g., qlong, are not
186 applicable.
187
188 There are no data alignment constraints for \a src. However, \a dest is
189 expected to be naturally aligned for type \c{T}.
190
191 If \a src and \a dest can be the same pointer, this function will perform
192 an in-place swap (if necessary). If they are not the same, the memory
193 regions must not overlap.
194
195 \sa qToBigEndian()
196 \sa qToLittleEndian()
197*/
198/*!
199 \fn template <typename T> void qToBigEndian(T src, void *dest)
200 \since 4.3
201 \relates <QtEndian>
202
203 Writes the number \a src with template type \c{T} to the memory location at \a dest
204 in big-endian byte order.
205
206 \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
207 quint64, or qint64. Other types of integers, e.g., qlong, are not
208 applicable.
209
210 There are no data alignment constraints for \a dest.
211
212 \note Since Qt 5.7, the type of the \a dest parameter is a void pointer.
213
214 \sa qFromBigEndian()
215 \sa qFromLittleEndian()
216 \sa qToLittleEndian()
217*/
218/*!
219 \fn template <typename T> T qToBigEndian(T src)
220 \since 4.3
221 \relates <QtEndian>
222 \overload
223
224 Converts \a src from host byte order and returns the number in big-endian byte order
225 representation of that number.
226 On CPU architectures where the host byte order is little-endian (such as x86) this
227 will return \a src with the byte order swapped; otherwise it will return \a src
228 unmodified.
229*/
230/*!
231 \fn template <typename T> T qToBigEndian(const void *src, qsizetype count, void *dest)
232 \since 5.12
233 \relates <QtEndian>
234
235 Reads \a count numbers from memory location \a src in the host byte order
236 and stores them in big-endian representation at \a dest. On CPU
237 architectures where the host byte order is little-endian (such as x86) this
238 will swap the byte order; otherwise it will just perform a \c memcpy from
239 \a src to \a dest.
240
241 \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
242 quint64, or qint64. Other types of integers, e.g., qlong, are not
243 applicable.
244
245 There are no data alignment constraints for \a dest. However, \a src is
246 expected to be naturally aligned for type \c{T}.
247
248 If \a src and \a dest can be the same pointer, this function will perform
249 an in-place swap (if necessary). If they are not the same, the memory
250 regions must not overlap.
251
252 \sa qFromLittleEndian()
253 \sa qToBigEndian()
254 \sa qToLittleEndian()
255*/
256/*!
257 \fn template <typename T> void qToLittleEndian(T src, void *dest)
258 \since 4.3
259 \relates <QtEndian>
260
261 Writes the number \a src with template type \c{T} to the memory location at \a dest
262 in little-endian byte order.
263
264 \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
265 quint64, or qint64. Other types of integers, e.g., qlong, are not
266 applicable.
267
268 There are no data alignment constraints for \a dest.
269
270 \note Since Qt 5.7, the type of the \a dest parameter is a void pointer.
271
272 \sa qFromBigEndian()
273 \sa qFromLittleEndian()
274 \sa qToBigEndian()
275*/
276/*!
277 \fn template <typename T> T qToLittleEndian(T src)
278 \since 4.3
279 \relates <QtEndian>
280 \overload
281
282 Converts \a src from host byte order and returns the number in little-endian byte
283 order representation of that number.
284 On CPU architectures where the host byte order is big-endian (such as PowerPC) this
285 will return \a src with the byte order swapped; otherwise it will return \a src
286 unmodified.
287*/
288/*!
289 \fn template <typename T> T qToLittleEndian(const void *src, qsizetype count, void *dest)
290 \since 5.12
291 \relates <QtEndian>
292
293 Reads \a count numbers from memory location \a src in the host byte order
294 and stores them in little-endian representation at \a dest. On CPU
295 architectures where the host byte order is big-endian (such as PowerPC)
296 this will swap the byte order; otherwise it will just perform a \c memcpy
297 from \a src to \a dest.
298
299 \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
300 quint64, or qint64. Other types of integers, e.g., qlong, are not
301 applicable.
302
303 There are no data alignment constraints for \a dest. However, \a src is
304 expected to be naturally aligned for type \c{T}.
305
306 If \a src and \a dest can be the same pointer, this function will perform
307 an in-place swap (if necessary). If they are not the same, the memory
308 regions must not overlap.
309
310 \sa qFromLittleEndian()
311 \sa qToBigEndian()
312 \sa qToLittleEndian()
313*/
314
315/*!
316 \class QLEInteger
317 \inmodule QtCore
318 \brief The QLEInteger class provides platform-independent little-endian integers.
319 \since 5.10
320
321 The template parameter \c T must be a C++ integer type:
322 \list
323 \li 8-bit: char, signed char, unsigned char, qint8, quint8
324 \li 16-bit: short, unsigned short, qint16, quint16, char16_t
325 \li 32-bit: int, unsigned int, qint32, quint32, char32_t
326 \li 64-bit: long long, unsigned long long, qint64, quint64
327 \li platform-specific size: long, unsigned long
328 \li pointer size: qintptr, quintptr, qptrdiff
329 \endlist
330
331 \note Using this class may be slower than using native integers, so only use it when
332 an exact endianness is needed.
333*/
334
335/*! \fn template <typename T> QLEInteger<T>::QLEInteger(T value)
336
337 Constructs a QLEInteger with the given \a value.
338*/
339
340/*! \fn template <typename T> QLEInteger &QLEInteger<T>::operator=(T i)
341
342 Assigns \a i to this QLEInteger and returns a reference to
343 this QLEInteger.
344*/
345
346/*!
347 \fn template <typename T> QLEInteger<T>::operator T() const
348
349 Returns the value of this QLEInteger as a native integer.
350*/
351
352/*!
353 \fn template <typename T> bool QLEInteger<T>::operator==(QLEInteger other) const
354
355 Returns \c true if the value of this QLEInteger is equal to the value of \a other.
356*/
357
358/*!
359 \fn template <typename T> bool QLEInteger<T>::operator!=(QLEInteger other) const
360
361 Returns \c true if the value of this QLEInteger is not equal to the value of \a other.
362*/
363
364/*!
365 \fn template <typename T> QLEInteger &QLEInteger<T>::operator+=(T i)
366
367 Adds \a i to this QLEInteger and returns a reference to
368 this object.
369*/
370
371/*!
372 \fn template <typename T> QLEInteger &QLEInteger<T>::operator-=(T i)
373
374 Subtracts \a i from this QLEInteger and returns a reference to
375 this object.
376*/
377
378/*!
379 \fn template <typename T> QLEInteger &QLEInteger<T>::operator*=(T i)
380
381 Multiplies \a i with this QLEInteger and returns a reference to
382 this object.
383*/
384
385/*!
386 \fn template <typename T> QLEInteger &QLEInteger<T>::operator/=(T i)
387
388 Divides this QLEInteger with \a i and returns a reference to
389 this object.
390*/
391
392/*!
393 \fn template <typename T> QLEInteger &QLEInteger<T>::operator%=(T i)
394
395 Sets this QLEInteger to the remainder of a division by \a i and
396 returns a reference to this object.
397*/
398
399/*!
400 \fn template <typename T> QLEInteger &QLEInteger<T>::operator>>=(T i)
401
402 Performs a left-shift by \a i on this QLEInteger and returns a
403 reference to this object.
404*/
405
406/*!
407 \fn template <typename T> QLEInteger &QLEInteger<T>::operator<<=(T i)
408
409 Performs a right-shift by \a i on this QLEInteger and returns a
410 reference to this object.
411*/
412
413/*!
414 \fn template <typename T> QLEInteger &QLEInteger<T>::operator|=(T i)
415
416 Performs a bitwise OR with \a i onto this QLEInteger and returns a reference to
417 this object.
418*/
419
420/*!
421 \fn template <typename T> QLEInteger &QLEInteger<T>::operator&=(T i)
422
423 Performs a bitwise AND with \a i onto this QLEInteger and returns a reference to
424 this object.
425*/
426
427/*!
428 \fn template <typename T> QLEInteger &QLEInteger<T>::operator^=(T i)
429
430 Performs a bitwise XOR with \a i onto this QLEInteger and returns a reference to
431 this object.
432*/
433
434/*!
435 \fn template <typename T> QLEInteger &QLEInteger<T>::operator++()
436
437 Performs a prefix ++ (increment) on this QLEInteger and returns a reference to
438 this object.
439*/
440
441/*!
442 \fn template <typename T> QLEInteger QLEInteger<T>::operator++(int)
443
444 Performs a postfix ++ (increment) on this QLEInteger and returns a reference to
445 this object.
446*/
447
448/*!
449 \fn template <typename T> QLEInteger &QLEInteger<T>::operator--()
450
451 Performs a prefix -- (decrement) on this QLEInteger and returns a reference to
452 this object.
453*/
454
455/*!
456 \fn template <typename T> QLEInteger QLEInteger<T>::operator--(int)
457
458 Performs a postfix -- (decrement) on this QLEInteger and returns a reference to
459 this object.
460*/
461
462/*!
463 \fn template <typename T> QLEInteger QLEInteger<T>::max()
464
465 Returns the maximum (finite) value representable by the numeric type T.
466*/
467
468/*!
469 \fn template <typename T> QLEInteger QLEInteger<T>::min()
470
471 Returns the minimum (finite) value representable by the numeric type T.
472*/
473
474/*!
475 \class QBEInteger
476 \inmodule QtCore
477 \brief The QBEInteger class provides platform-independent big-endian integers.
478 \since 5.10
479
480 The template parameter \c T must be a C++ integer type:
481 \list
482 \li 8-bit: char, signed char, unsigned char, qint8, quint8
483 \li 16-bit: short, unsigned short, qint16, quint16, char16_t (C++11)
484 \li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11)
485 \li 64-bit: long long, unsigned long long, qint64, quint64
486 \li platform-specific size: long, unsigned long
487 \li pointer size: qintptr, quintptr, qptrdiff
488 \endlist
489
490 \note Using this class may be slower than using native integers, so only use it when
491 an exact endianness is needed.
492*/
493
494/*! \fn template <typename T> QBEInteger<T>::QBEInteger(T value)
495
496 Constructs a QBEInteger with the given \a value.
497*/
498
499/*! \fn template <typename T> QBEInteger &QBEInteger<T>::operator=(T i)
500
501 Assigns \a i to this QBEInteger and returns a reference to
502 this QBEInteger.
503*/
504
505/*!
506 \fn template <typename T> QBEInteger<T>::operator T() const
507
508 Returns the value of this QBEInteger as a native integer.
509*/
510
511/*!
512 \fn template <typename T> bool QBEInteger<T>::operator==(QBEInteger other) const
513
514 Returns \c true if the value of this QBEInteger is equal to the value of \a other.
515*/
516
517/*!
518 \fn template <typename T> bool QBEInteger<T>::operator!=(QBEInteger other) const
519
520 Returns \c true if the value of this QBEInteger is not equal to the value of \a other.
521*/
522
523/*!
524 \fn template <typename T> QBEInteger &QBEInteger<T>::operator+=(T i)
525
526 Adds \a i to this QBEInteger and returns a reference to
527 this object.
528*/
529
530/*!
531 \fn template <typename T> QBEInteger &QBEInteger<T>::operator-=(T i)
532
533 Subtracts \a i from this QBEInteger and returns a reference to
534 this object.
535*/
536
537/*!
538 \fn template <typename T> QBEInteger &QBEInteger<T>::operator*=(T i)
539
540 Multiplies \a i with this QBEInteger and returns a reference to
541 this object.
542*/
543
544/*!
545 \fn template <typename T> QBEInteger &QBEInteger<T>::operator/=(T i)
546
547 Divides this QBEInteger with \a i and returns a reference to
548 this object.
549*/
550
551/*!
552 \fn template <typename T> QBEInteger &QBEInteger<T>::operator%=(T i)
553
554 Sets this QBEInteger to the remainder of a division by \a i and
555 returns a reference to this object.
556*/
557
558/*!
559 \fn template <typename T> QBEInteger &QBEInteger<T>::operator>>=(T i)
560
561 Performs a left-shift by \a i on this QBEInteger and returns a
562 reference to this object.
563*/
564
565/*!
566 \fn template <typename T> QBEInteger &QBEInteger<T>::operator<<=(T i)
567
568 Performs a right-shift by \a i on this QBEInteger and returns a
569 reference to this object.
570*/
571
572/*!
573 \fn template <typename T> QBEInteger &QBEInteger<T>::operator|=(T i)
574
575 Performs a bitwise OR with \a i onto this QBEInteger and returns a reference to
576 this object.
577*/
578
579/*!
580 \fn template <typename T> QBEInteger &QBEInteger<T>::operator&=(T i)
581
582 Performs a bitwise AND with \a i onto this QBEInteger and returns a reference to
583 this object.
584*/
585
586/*!
587 \fn template <typename T> QBEInteger &QBEInteger<T>::operator^=(T i)
588
589 Performs a bitwise XOR with \a i onto this QBEInteger and returns a reference to
590 this object.
591*/
592
593/*!
594 \fn template <typename T> QBEInteger &QBEInteger<T>::operator++()
595
596 Performs a prefix ++ (increment) on this QBEInteger and returns a reference to
597 this object.
598*/
599
600/*!
601 \fn template <typename T> QBEInteger QBEInteger<T>::operator++(int)
602
603 Performs a postfix ++ (increment) on this QBEInteger and returns a reference to
604 this object.
605*/
606
607/*!
608 \fn template <typename T> QBEInteger &QBEInteger<T>::operator--()
609
610 Performs a prefix -- (decrement) on this QBEInteger and returns a reference to
611 this object.
612*/
613
614/*!
615 \fn template <typename T> QBEInteger QBEInteger<T>::operator--(int)
616
617 Performs a postfix -- (decrement) on this QBEInteger and returns a reference to
618 this object.
619*/
620
621/*!
622 \fn template <typename T> QBEInteger QBEInteger<T>::max()
623
624 Returns the maximum (finite) value representable by the numeric type T.
625*/
626
627/*!
628 \fn template <typename T> QBEInteger QBEInteger<T>::min()
629
630 Returns the minimum (finite) value representable by the numeric type T.
631*/
632
633/*!
634 \typedef quint16_le
635 \relates <QtEndian>
636 \since 5.10
637
638 Typedef for QLEInteger<quint16>. This type is guaranteed to be stored in memory as
639 a 16-bit little-endian unsigned integer on all platforms supported by Qt.
640
641 \sa quint16
642*/
643
644/*!
645 \typedef quint32_le
646 \relates <QtEndian>
647 \since 5.10
648
649 Typedef for QLEInteger<quint32>. This type is guaranteed to be stored in memory as
650 a 32-bit little-endian unsigned integer on all platforms supported by Qt.
651
652 \sa quint32
653*/
654
655/*!
656 \typedef quint64_le
657 \relates <QtEndian>
658 \since 5.10
659
660 Typedef for QLEInteger<quint64>. This type is guaranteed to be stored in memory as
661 a 64-bit little-endian unsigned integer on all platforms supported by Qt.
662
663 \sa quint64
664*/
665
666/*!
667 \typedef quint16_be
668 \relates <QtEndian>
669 \since 5.10
670
671 Typedef for QBEInteger<quint16>. This type is guaranteed to be stored in memory as
672 a 16-bit big-endian unsigned integer on all platforms supported by Qt.
673
674 \sa quint16
675*/
676
677/*!
678 \typedef quint32_be
679 \relates <QtEndian>
680 \since 5.10
681
682 Typedef for QBEInteger<quint32>. This type is guaranteed to be stored in memory as
683 a 32-bit big-endian unsigned integer on all platforms supported by Qt.
684
685 \sa quint32
686*/
687
688/*!
689 \typedef quint64_be
690 \relates <QtEndian>
691 \since 5.10
692
693 Typedef for QBEInteger<quint64>. This type is guaranteed to be stored in memory as
694 a 64-bit big-endian unsigned integer on all platforms supported by Qt.
695
696 \sa quint64
697*/
698
699/*!
700 \typedef qint16_le
701 \relates <QtEndian>
702 \since 5.10
703
704 Typedef for QLEInteger<qint16>. This type is guaranteed to be stored in memory as
705 a 16-bit little-endian signed integer on all platforms supported by Qt.
706
707 \sa qint16
708*/
709
710/*!
711 \typedef qint32_le
712 \relates <QtEndian>
713 \since 5.10
714
715 Typedef for QLEInteger<qint32>. This type is guaranteed to be stored in memory as
716 a 32-bit little-endian signed integer on all platforms supported by Qt.
717
718 \sa qint32
719*/
720
721/*!
722 \typedef qint64_le
723 \relates <QtEndian>
724 \since 5.10
725
726 Typedef for QLEInteger<qint64>. This type is guaranteed to be stored in memory as
727 a 64-bit little-endian signed integer on all platforms supported by Qt.
728
729 \sa qint64
730*/
731
732/*!
733 \typedef qint16_be
734 \relates <QtEndian>
735 \since 5.10
736
737 Typedef for QBEInteger<qint16>. This type is guaranteed to be stored in memory as
738 a 16-bit big-endian signed integer on all platforms supported by Qt.
739
740 \sa qint16
741*/
742
743/*!
744 \typedef qint32_be
745 \relates <QtEndian>
746 \since 5.10
747
748 Typedef for QBEInteger<qint32>. This type is guaranteed to be stored in memory as
749 a 32-bit big-endian signed integer on all platforms supported by Qt.
750
751 \sa qint32
752*/
753
754/*!
755 \typedef qint64_be
756 \relates <QtEndian>
757 \since 5.10
758
759 Typedef for QBEInteger<qint64>. This type is guaranteed to be stored in memory as
760 a 64-bit big-endian signed integer on all platforms supported by Qt.
761
762 \sa qint64
763*/
764
765#if defined(__SSSE3__)
766using ShuffleMask = uchar[16];
767alignas(16) static const ShuffleMask shuffleMasks[3] = {
768 // 16-bit
769 {1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14},
770 // 32-bit
771 {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12},
772 // 64-bit
773 {7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8}
774};
775
776static size_t sseSwapLoop(const uchar *src, size_t bytes, uchar *dst,
777 const __m128i *shuffleMaskPtr) noexcept
778{
779 size_t i = 0;
780 const __m128i shuffleMask = _mm_load_si128(shuffleMaskPtr);
781
782# ifdef __AVX2__
783 const __m256i shuffleMask256 = _mm256_inserti128_si256(_mm256_castsi128_si256(shuffleMask), shuffleMask, 1);
784 for ( ; i + sizeof(__m256i) <= bytes; i += sizeof(__m256i)) {
785 __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + i));
786 data = _mm256_shuffle_epi8(data, shuffleMask256);
787 _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst + i), data);
788 }
789# else
790 for ( ; i + 2 * sizeof(__m128i) <= bytes; i += 2 * sizeof(__m128i)) {
791 __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i));
792 __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i) + 1);
793 data1 = _mm_shuffle_epi8(data1, shuffleMask);
794 data2 = _mm_shuffle_epi8(data2, shuffleMask);
795 _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data1);
796 _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i) + 1, data2);
797 }
798# endif
799
800 if (i + sizeof(__m128i) <= bytes) {
801 __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i));
802 data = _mm_shuffle_epi8(data, shuffleMask);
803 _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data);
804 i += sizeof(__m128i);
805 }
806
807 return i;
808}
809
810template <typename T> static Q_ALWAYS_INLINE
811size_t simdSwapLoop(const uchar *src, size_t bytes, uchar *dst) noexcept
812{
813 auto shuffleMaskPtr = reinterpret_cast<const __m128i *>(shuffleMasks[0]);
814 shuffleMaskPtr += qCountTrailingZeroBits(sizeof(T)) - 1;
815 size_t i = sseSwapLoop(src, bytes, dst, shuffleMaskPtr);
816
817 // epilogue
818 for (size_t _i = 0; i < bytes && _i < sizeof(__m128i); i += sizeof(T), _i += sizeof(T))
819 qbswap(qFromUnaligned<T>(src + i), dst + i);
820
821 // return the total, so the bswapLoop below does nothing
822 return bytes;
823}
824#elif defined(__SSE2__)
825template <typename T> static
826size_t simdSwapLoop(const uchar *, size_t, uchar *) noexcept
827{
828 // no generic version: we can't do 32- and 64-bit swaps easily,
829 // so we won't try
830 return 0;
831}
832
833template <> size_t simdSwapLoop<quint16>(const uchar *src, size_t bytes, uchar *dst) noexcept
834{
835 auto swapEndian = [](__m128i &data) {
836 __m128i lows = _mm_srli_epi16(data, 8);
837 __m128i highs = _mm_slli_epi16(data, 8);
838 data = _mm_xor_si128(lows, highs);
839 };
840
841 size_t i = 0;
842 for ( ; i + 2 * sizeof(__m128i) <= bytes; i += 2 * sizeof(__m128i)) {
843 __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i));
844 __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i) + 1);
845 swapEndian(data1);
846 swapEndian(data2);
847 _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data1);
848 _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i) + 1, data2);
849 }
850
851 if (i + sizeof(__m128i) <= bytes) {
852 __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i));
853 swapEndian(data);
854 _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data);
855 i += sizeof(__m128i);
856 }
857
858 // epilogue
859 for (size_t _i = 0 ; i < bytes && _i < sizeof(__m128i); i += sizeof(quint16), _i += sizeof(quint16))
860 qbswap(qFromUnaligned<quint16>(src + i), dst + i);
861
862 // return the total, so the bswapLoop below does nothing
863 return bytes;
864}
865#else
866template <typename T> static Q_ALWAYS_INLINE
867size_t simdSwapLoop(const uchar *, size_t, uchar *) noexcept
868{
869 return 0;
870}
871#endif
872
873template <typename T> static Q_ALWAYS_INLINE
874void *bswapLoop(const uchar *src, size_t n, uchar *dst) noexcept
875{
876 // Buffers cannot partially overlap: either they're identical or totally
877 // disjoint (note: they can be adjacent).
878 if (src != dst) {
879 quintptr s = quintptr(src);
880 quintptr d = quintptr(dst);
881 if (s < d)
882 Q_ASSERT(s + n <= d);
883 else
884 Q_ASSERT(d + n <= s);
885 }
886
887 size_t i = simdSwapLoop<T>(src, n, dst);
888
889 for (; i < n; i += sizeof(T))
890 qbswap(qFromUnaligned<T>(src + i), dst + i);
891 return dst + i;
892}
893
894template<>
895void *qbswap<2>(const void *source, qsizetype n, void *dest) noexcept
896{
897 const uchar *src = reinterpret_cast<const uchar *>(source);
898 uchar *dst = reinterpret_cast<uchar *>(dest);
899
900 return bswapLoop<quint16>(src, n << 1, dst);
901}
902
903template<>
904void *qbswap<4>(const void *source, qsizetype n, void *dest) noexcept
905{
906 const uchar *src = reinterpret_cast<const uchar *>(source);
907 uchar *dst = reinterpret_cast<uchar *>(dest);
908
909 return bswapLoop<quint32>(src, n << 2, dst);
910}
911
912template<>
913void *qbswap<8>(const void *source, qsizetype n, void *dest) noexcept
914{
915 const uchar *src = reinterpret_cast<const uchar *>(source);
916 uchar *dst = reinterpret_cast<uchar *>(dest);
917
918 return bswapLoop<quint64>(src, n << 3, dst);
919}
920
921QT_END_NAMESPACE
922