OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2014, Google Inc. All rights reserved. | |
Stephen Chennney
2014/06/20 14:46:56
We're using a much simpler header block now for ne
picksi
2014/06/23 15:30:43
Done.
| |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #ifndef SaturatedArithmeticAsm_h | |
32 #define SaturatedArithmeticAsm_h | |
33 | |
34 #include "wtf/CPU.h" | |
35 #include <limits> | |
36 #include <stdint.h> | |
37 | |
38 | |
39 ALWAYS_INLINE int32_t saturatedAddition(int32_t a, int32_t b) | |
40 { | |
41 int32_t result; | |
42 | |
43 asm("qadd %[output],%[first],%[second]" | |
44 : [output] "=r" (result) | |
45 : [first] "r" (a), | |
46 [second] "r" (b)); | |
47 | |
48 return result; | |
49 } | |
50 | |
51 ALWAYS_INLINE int32_t saturatedSubtraction(int32_t a, int32_t b) | |
52 { | |
53 int32_t result; | |
54 | |
55 asm("qsub %[output],%[first],%[second]" | |
56 : [output] "=r" (result) | |
57 : [first] "r" (a), | |
58 [second] "r" (b)); | |
59 | |
60 return result; | |
61 } | |
62 | |
63 inline int getMaxSaturatedSetResultForTesting(int FractionalShift) | |
64 { | |
65 // For ARM Asm version the set function maxes out to the biggest | |
66 // possible integer part with the fractional part zero'd out. e.g. 0x7fffffc 0. | |
67 return std::numeric_limits<int>::max() & ~((1 << FractionalShift)-1); | |
68 } | |
69 | |
70 inline int getMinSaturatedSetResultForTesting(int FractionalShift) | |
71 { | |
72 return std::numeric_limits<int>::min(); | |
73 } | |
74 | |
75 ALWAYS_INLINE int saturatedSet(int value, int FractionalShift) | |
76 { | |
77 // Figure out how many bits are left for storing the integer part of | |
78 // the fixed point number, and saturate our input to that | |
79 const int saturate = 32 - FractionalShift; | |
80 | |
81 int result; | |
82 | |
83 // The following ARM code will Saturate the passed value to the number of | |
84 // bits used for the whole part of the fixed point representation, then | |
85 // shift it up into place. This will result in the low <FractionShift> bits | |
86 // all being 0's. When the value saturates this gives a different result | |
87 // to from the C++ case; in the C++ code a saturated value has all the low | |
88 // bits set to 1 (for a +ve number at least). This cannot be done rapidly | |
89 // in ARM ... we live with the difference, for the sake of speed. | |
90 | |
91 asm("ssat %[output],%[saturate],%[value]\n\t" | |
92 "lsl %[output],%[shift]" | |
93 : [output] "=r" (result) | |
94 : [value] "r" (value), | |
95 [saturate] "n" (saturate), | |
96 [shift] "n" (FractionalShift)); | |
97 | |
98 return result; | |
99 } | |
100 | |
101 | |
102 ALWAYS_INLINE unsigned saturatedSet(unsigned value, int FractionalShift) | |
103 { | |
104 // Here we are being passed an unsigned value to saturate, | |
105 // even though the result is returned as a signed integer. The ARM | |
106 // instruction for unsigned saturation therefore needs to be given one | |
107 // less bit (i.e. the sign bit) for the saturation to work correctly; hence | |
108 // the '31' below. | |
109 const int saturate = 31 - FractionalShift; | |
110 | |
111 // The following ARM code will Saturate the passed value to the number of | |
112 // bits used for the whole part of the fixed point representation, then | |
113 // shift it up into place. This will result in the low <FractionShift> bits | |
114 // all being 0's. When the value saturates this gives a different result | |
115 // to from the C++ case; in the C++ code a saturated value has all the low | |
116 // bits set to 1. This cannot be done rapidly in ARM, so we live with the | |
117 // difference, for the sake of speed. | |
118 | |
119 unsigned result; | |
120 | |
121 asm("usat %[output],%[saturate],%[value]\n\t" | |
122 "lsl %[output],%[shift]" | |
123 : [output] "=r" (result) | |
124 : [value] "r" (value), | |
125 [saturate] "n" (saturate), | |
126 [shift] "n" (FractionalShift)); | |
127 | |
128 return result; | |
129 } | |
130 | |
131 #endif // SaturatedArithmeticAsm_h | |
OLD | NEW |