Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
safe_math_arm_impl.h
Go to the documentation of this file.
1// Copyright 2024 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CORE_FXCRT_NUMERICS_SAFE_MATH_ARM_IMPL_H_
6#define CORE_FXCRT_NUMERICS_SAFE_MATH_ARM_IMPL_H_
7
8#include <cassert>
9#include <type_traits>
10
11#include "core/fxcrt/numerics/safe_conversions.h"
12
13namespace pdfium {
14namespace internal {
15
16template <typename T, typename U>
18 static const bool is_supported =
20
21 // The following is not an assembler routine and is thus constexpr safe, it
22 // just emits much more efficient code than the Clang and GCC builtins for
23 // performing overflow-checked multiplication when a twice wider type is
24 // available. The below compiles down to 2-3 instructions, depending on the
25 // width of the types in use.
26 // As an example, an int32_t multiply compiles to:
27 // smull r0, r1, r0, r1
28 // cmp r1, r1, asr #31
29 // And an int16_t multiply compiles to:
30 // smulbb r1, r1, r0
31 // asr r2, r1, #16
32 // cmp r2, r1, asr #15
33 template <typename V>
34 static constexpr bool Do(T x, U y, V* result) {
35 using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
36 Promotion presult;
37
38 presult = static_cast<Promotion>(x) * static_cast<Promotion>(y);
39 if (!IsValueInRangeForNumericType<V>(presult))
40 return false;
41 *result = static_cast<V>(presult);
42 return true;
43 }
44};
45
46template <typename T, typename U>
48 static const bool is_supported =
51 int32_t,
52 typename BigEnoughPromotion<T, U>::type>::value;
53
54 template <typename V>
55 __attribute__((always_inline)) static V Do(T x, U y) {
56 // This will get promoted to an int, so let the compiler do whatever is
57 // clever and rely on the saturated cast to bounds check.
58 if (IsIntegerArithmeticSafe<int, T, U>::value)
59 return saturated_cast<V>(static_cast<int>(x) + static_cast<int>(y));
60
61 int32_t result;
62 int32_t x_i32 = checked_cast<int32_t>(x);
63 int32_t y_i32 = checked_cast<int32_t>(y);
64
65 asm("qadd %[result], %[first], %[second]"
66 : [result] "=r"(result)
67 : [first] "r"(x_i32), [second] "r"(y_i32));
68 return saturated_cast<V>(result);
69 }
70};
71
72template <typename T, typename U>
74 static const bool is_supported =
77 int32_t,
78 typename BigEnoughPromotion<T, U>::type>::value;
79
80 template <typename V>
81 __attribute__((always_inline)) static V Do(T x, U y) {
82 // This will get promoted to an int, so let the compiler do whatever is
83 // clever and rely on the saturated cast to bounds check.
84 if (IsIntegerArithmeticSafe<int, T, U>::value)
85 return saturated_cast<V>(static_cast<int>(x) - static_cast<int>(y));
86
87 int32_t result;
88 int32_t x_i32 = checked_cast<int32_t>(x);
89 int32_t y_i32 = checked_cast<int32_t>(y);
90
91 asm("qsub %[result], %[first], %[second]"
92 : [result] "=r"(result)
93 : [first] "r"(x_i32), [second] "r"(y_i32));
94 return saturated_cast<V>(result);
95 }
96};
97
98template <typename T, typename U>
100 static const bool is_supported =
101 kEnableAsmCode && CheckedMulFastAsmOp<T, U>::is_supported;
102
103 template <typename V>
104 __attribute__((always_inline)) static V Do(T x, U y) {
105 // Use the CheckedMulFastAsmOp for full-width 32-bit values, because
106 // it's fewer instructions than promoting and then saturating.
107 if (!IsIntegerArithmeticSafe<int32_t, T, U>::value &&
108 !IsIntegerArithmeticSafe<uint32_t, T, U>::value) {
109 V result;
110 return CheckedMulFastAsmOp<T, U>::Do(x, y, &result)
111 ? result
112 : CommonMaxOrMin<V>(IsValueNegative(x) ^ IsValueNegative(y));
113 }
114
115 assert((FastIntegerArithmeticPromotion<T, U>::is_contained));
116 using Promotion = typename FastIntegerArithmeticPromotion<T, U>::type;
117 return saturated_cast<V>(static_cast<Promotion>(x) *
118 static_cast<Promotion>(y));
119 }
120};
121
122} // namespace internal
123} // namespace pdfium
124
125#endif // CORE_FXCRT_NUMERICS_SAFE_MATH_ARM_IMPL_H_
constexpr bool kEnableAsmCode
#define assert
static constexpr bool Do(T x, U y, V *result)
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static V Do(T x