Chromium Code Reviews| Index: Source/wtf/asm/SaturatedArithmeticAsm.h |
| diff --git a/Source/wtf/asm/SaturatedArithmeticAsm.h b/Source/wtf/asm/SaturatedArithmeticAsm.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3ae82ec97376989708f19d73db72cf4ce0bf4d1b |
| --- /dev/null |
| +++ b/Source/wtf/asm/SaturatedArithmeticAsm.h |
| @@ -0,0 +1,131 @@ |
| +/* |
| + * 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.
|
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are |
| + * met: |
| + * |
| + * * Redistributions of source code must retain the above copyright |
| + * notice, this list of conditions and the following disclaimer. |
| + * * Redistributions in binary form must reproduce the above |
| + * copyright notice, this list of conditions and the following disclaimer |
| + * in the documentation and/or other materials provided with the |
| + * distribution. |
| + * * Neither the name of Google Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived from |
| + * this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| + */ |
| + |
| +#ifndef SaturatedArithmeticAsm_h |
| +#define SaturatedArithmeticAsm_h |
| + |
| +#include "wtf/CPU.h" |
| +#include <limits> |
| +#include <stdint.h> |
| + |
| + |
| +ALWAYS_INLINE int32_t saturatedAddition(int32_t a, int32_t b) |
| +{ |
| + int32_t result; |
| + |
| + asm("qadd %[output],%[first],%[second]" |
| + : [output] "=r" (result) |
| + : [first] "r" (a), |
| + [second] "r" (b)); |
| + |
| + return result; |
| +} |
| + |
| +ALWAYS_INLINE int32_t saturatedSubtraction(int32_t a, int32_t b) |
| +{ |
| + int32_t result; |
| + |
| + asm("qsub %[output],%[first],%[second]" |
| + : [output] "=r" (result) |
| + : [first] "r" (a), |
| + [second] "r" (b)); |
| + |
| + return result; |
| +} |
| + |
| +inline int getMaxSaturatedSetResultForTesting(int FractionalShift) |
| +{ |
| + // For ARM Asm version the set function maxes out to the biggest |
| + // possible integer part with the fractional part zero'd out. e.g. 0x7fffffc0. |
| + return std::numeric_limits<int>::max() & ~((1 << FractionalShift)-1); |
| +} |
| + |
| +inline int getMinSaturatedSetResultForTesting(int FractionalShift) |
| +{ |
| + return std::numeric_limits<int>::min(); |
| +} |
| + |
| +ALWAYS_INLINE int saturatedSet(int value, int FractionalShift) |
| +{ |
| + // Figure out how many bits are left for storing the integer part of |
| + // the fixed point number, and saturate our input to that |
| + const int saturate = 32 - FractionalShift; |
| + |
| + int result; |
| + |
| + // The following ARM code will Saturate the passed value to the number of |
| + // bits used for the whole part of the fixed point representation, then |
| + // shift it up into place. This will result in the low <FractionShift> bits |
| + // all being 0's. When the value saturates this gives a different result |
| + // to from the C++ case; in the C++ code a saturated value has all the low |
| + // bits set to 1 (for a +ve number at least). This cannot be done rapidly |
| + // in ARM ... we live with the difference, for the sake of speed. |
| + |
| + asm("ssat %[output],%[saturate],%[value]\n\t" |
| + "lsl %[output],%[shift]" |
| + : [output] "=r" (result) |
| + : [value] "r" (value), |
| + [saturate] "n" (saturate), |
| + [shift] "n" (FractionalShift)); |
| + |
| + return result; |
| +} |
| + |
| + |
| +ALWAYS_INLINE unsigned saturatedSet(unsigned value, int FractionalShift) |
| +{ |
| + // Here we are being passed an unsigned value to saturate, |
| + // even though the result is returned as a signed integer. The ARM |
| + // instruction for unsigned saturation therefore needs to be given one |
| + // less bit (i.e. the sign bit) for the saturation to work correctly; hence |
| + // the '31' below. |
| + const int saturate = 31 - FractionalShift; |
| + |
| + // The following ARM code will Saturate the passed value to the number of |
| + // bits used for the whole part of the fixed point representation, then |
| + // shift it up into place. This will result in the low <FractionShift> bits |
| + // all being 0's. When the value saturates this gives a different result |
| + // to from the C++ case; in the C++ code a saturated value has all the low |
| + // bits set to 1. This cannot be done rapidly in ARM, so we live with the |
| + // difference, for the sake of speed. |
| + |
| + unsigned result; |
| + |
| + asm("usat %[output],%[saturate],%[value]\n\t" |
| + "lsl %[output],%[shift]" |
| + : [output] "=r" (result) |
| + : [value] "r" (value), |
| + [saturate] "n" (saturate), |
| + [shift] "n" (FractionalShift)); |
| + |
| + return result; |
| +} |
| + |
| +#endif // SaturatedArithmeticAsm_h |