diff options
author | Show Liu <show.liu@linaro.org> | 2015-06-04 18:07:43 +0800 |
---|---|---|
committer | Gil Pitney <gil.pitney@linaro.org> | 2015-06-05 17:21:49 +0000 |
commit | dff2da92de7f00d899954180562e71e8ff7b370b (patch) | |
tree | a53c8eab45886bce9a3004c38f1bcd29a291c58f | |
parent | e65e7cbfad8685359a7e2a6b32abcaaa810ad19f (diff) |
fixed the sub_sat() builin function crash issue
-rw-r--r-- | src/builtins/sub_sat.cl | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/builtins/sub_sat.cl b/src/builtins/sub_sat.cl index 78442f0..84fbbd9 100644 --- a/src/builtins/sub_sat.cl +++ b/src/builtins/sub_sat.cl @@ -27,6 +27,89 @@ *****************************************************************************/ #include "cpu.h" +_CLC_OVERLOAD _CLC_DECL char sub_sat(char x, char y) +{ + int bits = CHAR_BIT * sizeof(char); + char min = (char)1 << (char)(bits-1); + char max = min - (char)1; + return ((x^y) >= (char)0 ? + /* different signs: no overflow/underflow */ + x-y : x >= (char)0 ? + /* x and y positive: can overflow */ + (x > max+y ? max : x-y) : + /* x and y negative: can underflow */ + (x < min+y ? min : x-y)); + +} + +_CLC_OVERLOAD _CLC_DECL short sub_sat(short x, short y) +{ + int bits = CHAR_BIT * sizeof(short); + short min = (short)1 << (short)(bits-1); + short max = min - (short)1; + return ((x^y) >= (short)0 ? + /* different signs: no overflow/underflow */ + x-y : x >= (short)0 ? + /* x and y positive: can overflow */ + (x > max+y ? max : x-y) : + /* x and y negative: can underflow */ + (x < min+y ? min : x-y)); + +} +_CLC_OVERLOAD _CLC_DECL int sub_sat(int x, int y) +{ + int bits = CHAR_BIT * sizeof(int); + int min = (int)1 << (int)(bits-1); + int max = min - (int)1; + return ((x^y) >= (int)0 ? + /* different signs: no overflow/underflow */ + x-y : x >= (int)0 ? + /* x and y positive: can overflow */ + (x > max+y ? max : x-y) : + /* x and y negative: can underflow */ + (x < min+y ? min : x-y)); + +} + +_CLC_OVERLOAD _CLC_DECL long sub_sat(long x, long y) +{ + int bits = CHAR_BIT * sizeof(long); + long min = (long)1 << (long)(bits-1); + long max = min - (long)1; + return ((x^y) >= (long)0 ? + /* different signs: no overflow/underflow */ + x-y : x >= (long)0 ? + /* x and y positive: can overflow */ + (x > max+y ? max : x-y) : + /* x and y negative: can underflow */ + (x < min+y ? min : x-y)); + +} + +_CLC_OVERLOAD _CLC_DECL uchar sub_sat(uchar x, uchar y) +{ + uchar min = (uchar)0; + return (x < min+y ? min : x-y); +} + +_CLC_OVERLOAD _CLC_DECL ushort sub_sat(ushort x, ushort y) +{ + ushort min = (ushort)0; + return (x < min+y ? min : x-y); +} + +_CLC_OVERLOAD _CLC_DECL uint sub_sat(uint x, uint y) +{ + uint min = (uint)0; + return (x < min+y ? min : x-y); +} + +_CLC_OVERLOAD _CLC_DECL ulong sub_sat(ulong x, ulong y) +{ + ulong min = (ulong)0; + return (x < min+y ? min : x-y); +} + BINARY_VEC_DEF(char, char, sub_sat, sub_sat) BINARY_VEC_DEF(uchar, uchar, sub_sat, sub_sat) BINARY_VEC_DEF(short, short, sub_sat, sub_sat) |