Revision 6ddbc6e4 target-arm/helper.c

b/target-arm/helper.c
1922 1922
}
1923 1923

  
1924 1924
#endif
1925

  
1926
/* Note that signed overflow is undefined in C.  The following routines are
1927
   careful to use unsigned types where modulo arithmetic is required.
1928
   Failure to do so _will_ break on newer gcc.  */
1929

  
1930
/* Signed saturating arithmetic.  */
1931

  
1932
/* Perform 16-bit signed satruating addition.  */
1933
static inline uint16_t add16_sat(uint16_t a, uint16_t b)
1934
{
1935
    uint16_t res;
1936

  
1937
    res = a + b;
1938
    if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
1939
        if (a & 0x8000)
1940
            res = 0x8000;
1941
        else
1942
            res = 0x7fff;
1943
    }
1944
    return res;
1945
}
1946

  
1947
/* Perform 8-bit signed satruating addition.  */
1948
static inline uint8_t add8_sat(uint8_t a, uint8_t b)
1949
{
1950
    uint8_t res;
1951

  
1952
    res = a + b;
1953
    if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
1954
        if (a & 0x80)
1955
            res = 0x80;
1956
        else
1957
            res = 0x7f;
1958
    }
1959
    return res;
1960
}
1961

  
1962
/* Perform 16-bit signed satruating subtraction.  */
1963
static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
1964
{
1965
    uint16_t res;
1966

  
1967
    res = a - b;
1968
    if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
1969
        if (a & 0x8000)
1970
            res = 0x8000;
1971
        else
1972
            res = 0x7fff;
1973
    }
1974
    return res;
1975
}
1976

  
1977
/* Perform 8-bit signed satruating subtraction.  */
1978
static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
1979
{
1980
    uint8_t res;
1981

  
1982
    res = a - b;
1983
    if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
1984
        if (a & 0x80)
1985
            res = 0x80;
1986
        else
1987
            res = 0x7f;
1988
    }
1989
    return res;
1990
}
1991

  
1992
#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
1993
#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
1994
#define ADD8(a, b, n)  RESULT(add8_sat(a, b), n, 8);
1995
#define SUB8(a, b, n)  RESULT(sub8_sat(a, b), n, 8);
1996
#define PFX q
1997

  
1998
#include "op_addsub.h"
1999

  
2000
/* Unsigned saturating arithmetic.  */
2001
static inline uint16_t add16_usat(uint16_t a, uint8_t b)
2002
{
2003
    uint16_t res;
2004
    res = a + b;
2005
    if (res < a)
2006
        res = 0xffff;
2007
    return res;
2008
}
2009

  
2010
static inline uint16_t sub16_usat(uint16_t a, uint8_t b)
2011
{
2012
    if (a < b)
2013
        return a - b;
2014
    else
2015
        return 0;
2016
}
2017

  
2018
static inline uint8_t add8_usat(uint8_t a, uint8_t b)
2019
{
2020
    uint8_t res;
2021
    res = a + b;
2022
    if (res < a)
2023
        res = 0xff;
2024
    return res;
2025
}
2026

  
2027
static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
2028
{
2029
    if (a < b)
2030
        return a - b;
2031
    else
2032
        return 0;
2033
}
2034

  
2035
#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
2036
#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
2037
#define ADD8(a, b, n)  RESULT(add8_usat(a, b), n, 8);
2038
#define SUB8(a, b, n)  RESULT(sub8_usat(a, b), n, 8);
2039
#define PFX uq
2040

  
2041
#include "op_addsub.h"
2042

  
2043
/* Signed modulo arithmetic.  */
2044
#define SARITH16(a, b, n, op) do { \
2045
    int32_t sum; \
2046
    sum = (int16_t)((uint16_t)(a) op (uint16_t)(b)); \
2047
    RESULT(sum, n, 16); \
2048
    if (sum >= 0) \
2049
        ge |= 3 << (n * 2); \
2050
    } while(0)
2051

  
2052
#define SARITH8(a, b, n, op) do { \
2053
    int32_t sum; \
2054
    sum = (int8_t)((uint8_t)(a) op (uint8_t)(b)); \
2055
    RESULT(sum, n, 8); \
2056
    if (sum >= 0) \
2057
        ge |= 1 << n; \
2058
    } while(0)
2059

  
2060

  
2061
#define ADD16(a, b, n) SARITH16(a, b, n, +)
2062
#define SUB16(a, b, n) SARITH16(a, b, n, -)
2063
#define ADD8(a, b, n)  SARITH8(a, b, n, +)
2064
#define SUB8(a, b, n)  SARITH8(a, b, n, -)
2065
#define PFX s
2066
#define ARITH_GE
2067

  
2068
#include "op_addsub.h"
2069

  
2070
/* Unsigned modulo arithmetic.  */
2071
#define ADD16(a, b, n) do { \
2072
    uint32_t sum; \
2073
    sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
2074
    RESULT(sum, n, 16); \
2075
    if ((sum >> 16) == 0) \
2076
        ge |= 3 << (n * 2); \
2077
    } while(0)
2078

  
2079
#define ADD8(a, b, n) do { \
2080
    uint32_t sum; \
2081
    sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
2082
    RESULT(sum, n, 8); \
2083
    if ((sum >> 8) == 0) \
2084
        ge |= 3 << (n * 2); \
2085
    } while(0)
2086

  
2087
#define SUB16(a, b, n) do { \
2088
    uint32_t sum; \
2089
    sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
2090
    RESULT(sum, n, 16); \
2091
    if ((sum >> 16) == 0) \
2092
        ge |= 3 << (n * 2); \
2093
    } while(0)
2094

  
2095
#define SUB8(a, b, n) do { \
2096
    uint32_t sum; \
2097
    sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
2098
    RESULT(sum, n, 8); \
2099
    if ((sum >> 8) == 0) \
2100
        ge |= 3 << (n * 2); \
2101
    } while(0)
2102

  
2103
#define PFX u
2104
#define ARITH_GE
2105

  
2106
#include "op_addsub.h"
2107

  
2108
/* Halved signed arithmetic.  */
2109
#define ADD16(a, b, n) \
2110
  RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
2111
#define SUB16(a, b, n) \
2112
  RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
2113
#define ADD8(a, b, n) \
2114
  RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
2115
#define SUB8(a, b, n) \
2116
  RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
2117
#define PFX sh
2118

  
2119
#include "op_addsub.h"
2120

  
2121
/* Halved unsigned arithmetic.  */
2122
#define ADD16(a, b, n) \
2123
  RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
2124
#define SUB16(a, b, n) \
2125
  RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
2126
#define ADD8(a, b, n) \
2127
  RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
2128
#define SUB8(a, b, n) \
2129
  RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
2130
#define PFX uh
2131

  
2132
#include "op_addsub.h"
2133

  
2134
static inline uint8_t do_usad(uint8_t a, uint8_t b)
2135
{
2136
    if (a > b)
2137
        return a - b;
2138
    else
2139
        return b - a;
2140
}
2141

  
2142
/* Unsigned sum of absolute byte differences.  */
2143
uint32_t HELPER(usad8)(uint32_t a, uint32_t b)
2144
{
2145
    uint32_t sum;
2146
    sum = do_usad(a, b);
2147
    sum += do_usad(a >> 8, b >> 8);
2148
    sum += do_usad(a >> 16, b >>16);
2149
    sum += do_usad(a >> 24, b >> 24);
2150
    return sum;
2151
}
2152

  
2153
/* For ARMv6 SEL instruction.  */
2154
uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
2155
{
2156
    uint32_t mask;
2157

  
2158
    mask = 0;
2159
    if (flags & 1)
2160
        mask |= 0xff;
2161
    if (flags & 2)
2162
        mask |= 0xff00;
2163
    if (flags & 4)
2164
        mask |= 0xff0000;
2165
    if (flags & 8)
2166
        mask |= 0xff000000;
2167
    return (a & mask) | (b & ~mask);
2168
}
2169

  

Also available in: Unified diff