diff options
author | Xin Li <delphij@google.com> | 2019-07-01 20:59:31 +0000 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2019-07-01 20:59:31 +0000 |
commit | 5c5eea5c2c4dc32131995c3f8d2df4b6d4dca2ec (patch) | |
tree | ad58e0d7eb21e8f4a7f75790d3275b7301e71554 /silk | |
parent | 4c94a92893f71fe69d581f2a10bdaee96ff806d1 (diff) | |
parent | 20a7fdb4655e7f22e73db78f9a47f78eb0342222 (diff) | |
download | libopus-5c5eea5c2c4dc32131995c3f8d2df4b6d4dca2ec.tar.gz |
DO NOT MERGE - Merge qt-dev-plus-aosp-without-vendor (5699924) into stage-aosp-master
Bug: 134405016
Change-Id: I2e03fbdac94033bd9ac023500ae911a376a0088f
Diffstat (limited to 'silk')
-rw-r--r-- | silk/SigProc_FIX.h | 29 | ||||
-rw-r--r-- | silk/macros.h | 31 |
2 files changed, 50 insertions, 10 deletions
diff --git a/silk/SigProc_FIX.h b/silk/SigProc_FIX.h index f9ae3263..a9068908 100644 --- a/silk/SigProc_FIX.h +++ b/silk/SigProc_FIX.h @@ -448,13 +448,29 @@ static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot ) /* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour (just standard two's complement implementation-specific behaviour) */ -#define silk_ADD32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) + (opus_uint32)(b))) +static OPUS_INLINE opus_int32 silk_ADD32_ovflw(opus_int32 a, opus_int32 b) { + opus_int32 _c; + __builtin_add_overflow(a, b, &_c); + return _c; +} + /* Subtractss two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour (just standard two's complement implementation-specific behaviour) */ -#define silk_SUB32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) - (opus_uint32)(b))) +static OPUS_INLINE opus_int32 silk_SUB32_ovflw(opus_int32 a, opus_int32 b) { + opus_int32 _c; + __builtin_sub_overflow(a, b, &_c); + return _c; +} /* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */ -#define silk_MLA_ovflw(a32, b32, c32) silk_ADD32_ovflw((a32), (opus_uint32)(b32) * (opus_uint32)(c32)) +/* .. also ignoring multiply overflows; caller has comment about this happening occasionally */ +static OPUS_INLINE opus_int32 silk_MLA_ovflw(opus_int32 a, opus_int32 b, opus_int32 c) { + opus_int32 _d, _e; + __builtin_mul_overflow(b, c, &_d); + __builtin_add_overflow(a, _d, &_e); + return _e; +} + #define silk_SMLABB_ovflw(a32, b32, c32) (silk_ADD32_ovflw((a32) , ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32)))) #define silk_DIV32_16(a32, b16) ((opus_int32)((a32) / (b16))) @@ -496,7 +512,12 @@ static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot ) /* Add with saturation for positive input values */ #define silk_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b))) #define silk_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b))) -#define silk_ADD_POS_SAT32(a, b) ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b))) +static OPUS_INLINE opus_int32 silk_ADD_POS_SAT32(opus_int32 a, opus_int32 b) { + opus_int32 _c; + if (__builtin_add_overflow(a, b, &_c)) + return silk_int32_MAX; + return _c; +} #define silk_LSHIFT8(a, shift) ((opus_int8)((opus_uint8)(a)<<(shift))) /* shift >= 0, shift < 8 */ #define silk_LSHIFT16(a, shift) ((opus_int16)((opus_uint16)(a)<<(shift))) /* shift >= 0, shift < 16 */ diff --git a/silk/macros.h b/silk/macros.h index 3c67b6e5..00ccca31 100644 --- a/silk/macros.h +++ b/silk/macros.h @@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE. #endif #include "opus_types.h" +#include "typedef.h" #include "opus_defines.h" #include "arch.h" @@ -96,13 +97,31 @@ POSSIBILITY OF SUCH DAMAGE. #endif /* add/subtract with output saturated */ -#define silk_ADD_SAT32(a, b) ((((opus_uint32)(a) + (opus_uint32)(b)) & 0x80000000) == 0 ? \ - ((((a) & (b)) & 0x80000000) != 0 ? silk_int32_MIN : (a)+(b)) : \ - ((((a) | (b)) & 0x80000000) == 0 ? silk_int32_MAX : (a)+(b)) ) +/* use clang builtin overflow detectors */ +static OPUS_INLINE opus_int32 silk_ADD_SAT32(opus_int32 a, opus_int32 b) { + opus_int32 c; + if (__builtin_add_overflow(a, b, &c)) { + // overflowed + if (a < 0) // neg+X can only overflow towards -inf + c = silk_int32_MIN; + else + c = silk_int32_MAX; + } + return c; +} -#define silk_SUB_SAT32(a, b) ((((opus_uint32)(a)-(opus_uint32)(b)) & 0x80000000) == 0 ? \ - (( (a) & ((b)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a)-(b)) : \ - ((((a)^0x80000000) & (b) & 0x80000000) ? silk_int32_MAX : (a)-(b)) ) +/* use clang builtin overflow detectors */ +static OPUS_INLINE opus_int32 silk_SUB_SAT32(opus_int32 a, opus_int32 b) { + opus_int32 c; + if (__builtin_sub_overflow(a, b, &c)) { + // overflowed, + if (a < 0) // neg-X only overflows towards -inf + c = silk_int32_MIN; + else + c = silk_int32_MAX; + } + return c; +} #if defined(MIPSr1_ASM) #include "mips/macros_mipsr1.h" |