15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2012, Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef SaturatedArithmetic_h
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SaturatedArithmetic_h
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "wtf/CPU.h"
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <limits>
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <stdint.h>
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
38197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if CPU(ARM) && COMPILER(GCC) && __OPTIMIZE__
39197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
40197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// If we're building ARM on GCC we replace the C++ versions with some
41197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch// native ARM assembly for speed.
42197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "wtf/asm/SaturatedArithmeticARM.h"
43197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
44197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#else
45197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
46d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)ALWAYS_INLINE int32_t saturatedAddition(int32_t a, int32_t b)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t ua = a;
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t ub = b;
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t result = ua + ub;
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
52197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Can only overflow if the signed bit of the two values match. If the
53197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // signed bit of the result and one of the values differ it overflowed.
54197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
55197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (~(ua ^ ub) & (result ^ ua) & (1 << 31))
56197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return std::numeric_limits<int>::max() + (ua >> 31);
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
61d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)ALWAYS_INLINE int32_t saturatedSubtraction(int32_t a, int32_t b)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t ua = a;
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t ub = b;
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    uint32_t result = ua - ub;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
67197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Can only overflow if the signed bit of the two input values differ. If
68197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // the signed bit of the result and the first value differ it overflowed.
69197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
70197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if ((ua ^ ub) & (result ^ ua) & (1 << 31))
71197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return std::numeric_limits<int>::max() + (ua >> 31);
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
76197021e6b966cfb06891637935ef33fff06433d1Ben Murdochinline int getMaxSaturatedSetResultForTesting(int FractionalShift)
77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // For C version the set function maxes out to max int, this differs from
79197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // the ARM asm version, see SaturatedArithmetiARM.h for the equivalent asm
80197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // version.
81197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return std::numeric_limits<int>::max();
82197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
83197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
84197021e6b966cfb06891637935ef33fff06433d1Ben Murdochinline int getMinSaturatedSetResultForTesting(int FractionalShift)
85197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
86197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return std::numeric_limits<int>::min();
87197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
88197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
89197021e6b966cfb06891637935ef33fff06433d1Ben MurdochALWAYS_INLINE int saturatedSet(int value, int FractionalShift)
90197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
91197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    const int intMaxForLayoutUnit =
92197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        std::numeric_limits<int>::max() >> FractionalShift;
93197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    const int intMinForLayoutUnit =
95197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        std::numeric_limits<int>::min() >> FractionalShift;
96197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
97197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (value > intMaxForLayoutUnit)
98197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return std::numeric_limits<int>::max();
99197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
100197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (value < intMinForLayoutUnit)
101197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return std::numeric_limits<int>::min();
102197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
103197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return value << FractionalShift;
104197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
105197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
106197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
107197021e6b966cfb06891637935ef33fff06433d1Ben MurdochALWAYS_INLINE int saturatedSet(unsigned value, int FractionalShift)
108197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
109197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    const unsigned intMaxForLayoutUnit =
110197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        std::numeric_limits<int>::max() >> FractionalShift;
111197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
112197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (value >= intMaxForLayoutUnit)
113197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return std::numeric_limits<int>::max();
114197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
115197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return value << FractionalShift;
116197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
117197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
118197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif // CPU(ARM) && COMPILER(GCC)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // SaturatedArithmetic_h
120