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