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