• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors. All rights reserved.
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 BASE_NUMERICS_SATURATED_ARITHMETIC_ARM_H_
6 #define BASE_NUMERICS_SATURATED_ARITHMETIC_ARM_H_
7 
8 #include <limits>
9 
10 namespace base {
11 
SaturatedAddition(int32_t a,int32_t b)12 inline int32_t SaturatedAddition(int32_t a, int32_t b) {
13   int32_t result;
14 
15   asm("qadd %[output],%[first],%[second]"
16       : [output] "=r"(result)
17       : [first] "r"(a), [second] "r"(b));
18 
19   return result;
20 }
21 
SaturatedSubtraction(int32_t a,int32_t b)22 inline int32_t SaturatedSubtraction(int32_t a, int32_t b) {
23   int32_t result;
24 
25   asm("qsub %[output],%[first],%[second]"
26       : [output] "=r"(result)
27       : [first] "r"(a), [second] "r"(b));
28 
29   return result;
30 }
31 
SaturatedNegative(int32_t a)32 inline int32_t SaturatedNegative(int32_t a) {
33   return SaturatedSubtraction(0, a);
34 }
35 
SaturatedAbsolute(int32_t a)36 inline int32_t SaturatedAbsolute(int32_t a) {
37   if (a >= 0)
38     return a;
39   return SaturatedNegative(a);
40 }
41 
GetMaxSaturatedSetResultForTesting(int fractional_shift)42 inline int GetMaxSaturatedSetResultForTesting(int fractional_shift) {
43   // For ARM Asm version the set function maxes out to the biggest
44   // possible integer part with the fractional part zero'd out.
45   // e.g. 0x7fffffc0.
46   return std::numeric_limits<int>::max() & ~((1 << fractional_shift) - 1);
47 }
48 
GetMinSaturatedSetResultForTesting(int fractional_shift)49 inline int GetMinSaturatedSetResultForTesting(int fractional_shift) {
50   return std::numeric_limits<int>::min();
51 }
52 
53 template <int fractional_shift>
SaturatedSet(int value)54 inline int SaturatedSet(int value) {
55   // Figure out how many bits are left for storing the integer part of
56   // the fixed point number, and saturate our input to that
57   enum { Saturate = 32 - fractional_shift };
58 
59   int result;
60 
61   // The following ARM code will Saturate the passed value to the number of
62   // bits used for the whole part of the fixed point representation, then
63   // shift it up into place. This will result in the low <FractionShift> bits
64   // all being 0's. When the value saturates this gives a different result
65   // to from the C++ case; in the C++ code a saturated value has all the low
66   // bits set to 1 (for a +ve number at least). This cannot be done rapidly
67   // in ARM ... we live with the difference, for the sake of speed.
68 
69   asm("ssat %[output],%[saturate],%[value]\n\t"
70       "lsl  %[output],%[shift]"
71       : [output] "=r"(result)
72       : [value] "r"(value), [saturate] "n"(Saturate),
73         [shift] "n"(fractional_shift));
74 
75   return result;
76 }
77 
78 template <int fractional_shift>
SaturatedSet(unsigned value)79 inline int SaturatedSet(unsigned value) {
80   // Here we are being passed an unsigned value to saturate,
81   // even though the result is returned as a signed integer. The ARM
82   // instruction for unsigned saturation therefore needs to be given one
83   // less bit (i.e. the sign bit) for the saturation to work correctly; hence
84   // the '31' below.
85   enum { Saturate = 31 - fractional_shift };
86 
87   // The following ARM code will Saturate the passed value to the number of
88   // bits used for the whole part of the fixed point representation, then
89   // shift it up into place. This will result in the low <FractionShift> bits
90   // all being 0's. When the value saturates this gives a different result
91   // to from the C++ case; in the C++ code a saturated value has all the low
92   // bits set to 1. This cannot be done rapidly in ARM, so we live with the
93   // difference, for the sake of speed.
94 
95   int result;
96 
97   asm("usat %[output],%[saturate],%[value]\n\t"
98       "lsl  %[output],%[shift]"
99       : [output] "=r"(result)
100       : [value] "r"(value), [saturate] "n"(Saturate),
101         [shift] "n"(fractional_shift));
102 
103   return result;
104 }
105 
106 }  // namespace base
107 
108 #endif  // BASE_NUMERICS_SATURATED_ARITHMETIC_ARM_H_
109