Commit 6ddbc6e4cfbfa0937fdebd8aa7b518d8b7fd118b
1 parent
3670669c
ARM TCG conversion 7/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4144 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
556 additions
and
449 deletions
target-arm/helper.c
| ... | ... | @@ -1922,3 +1922,248 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, |
| 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 | + | ... | ... |
target-arm/helpers.h
| 1 | -#define DEF_HELPER(name, ret, args) ret helper_##name args; | |
| 1 | +#define DEF_HELPER(name, ret, args) ret glue(helper_,name) args; | |
| 2 | 2 | |
| 3 | 3 | #ifdef GEN_HELPER |
| 4 | 4 | #define DEF_HELPER_1_1(name, ret, args) \ |
| ... | ... | @@ -13,10 +13,18 @@ static inline void gen_helper_##name(TCGv ret, TCGv arg1, TCGv arg2) \ |
| 13 | 13 | { \ |
| 14 | 14 | tcg_gen_helper_1_2(helper_##name, ret, arg1, arg2); \ |
| 15 | 15 | } |
| 16 | +#define DEF_HELPER_1_3(name, ret, args) \ | |
| 17 | +DEF_HELPER(name, ret, args) \ | |
| 18 | +static inline void gen_helper_##name(TCGv ret, \ | |
| 19 | + TCGv arg1, TCGv arg2, TCGv arg3) \ | |
| 20 | +{ \ | |
| 21 | + tcg_gen_helper_1_3(helper_##name, ret, arg1, arg2, arg3); \ | |
| 22 | +} | |
| 16 | 23 | #else /* !GEN_HELPER */ |
| 17 | 24 | #define DEF_HELPER_1_1 DEF_HELPER |
| 18 | 25 | #define DEF_HELPER_1_2 DEF_HELPER |
| 19 | -#define HELPER(x) helper_##x | |
| 26 | +#define DEF_HELPER_1_3 DEF_HELPER | |
| 27 | +#define HELPER(x) glue(helper_,x) | |
| 20 | 28 | #endif |
| 21 | 29 | |
| 22 | 30 | DEF_HELPER_1_1(clz, uint32_t, (uint32_t)) |
| ... | ... | @@ -33,6 +41,40 @@ DEF_HELPER_1_2(sdiv, int32_t, (int32_t, int32_t)) |
| 33 | 41 | DEF_HELPER_1_2(udiv, uint32_t, (uint32_t, uint32_t)) |
| 34 | 42 | DEF_HELPER_1_1(rbit, uint32_t, (uint32_t)) |
| 35 | 43 | |
| 44 | +#define PAS_OP(pfx) \ | |
| 45 | + DEF_HELPER_1_3(pfx ## add8, uint32_t, (uint32_t, uint32_t, uint32_t *)) \ | |
| 46 | + DEF_HELPER_1_3(pfx ## sub8, uint32_t, (uint32_t, uint32_t, uint32_t *)) \ | |
| 47 | + DEF_HELPER_1_3(pfx ## sub16, uint32_t, (uint32_t, uint32_t, uint32_t *)) \ | |
| 48 | + DEF_HELPER_1_3(pfx ## add16, uint32_t, (uint32_t, uint32_t, uint32_t *)) \ | |
| 49 | + DEF_HELPER_1_3(pfx ## addsubx, uint32_t, (uint32_t, uint32_t, uint32_t *)) \ | |
| 50 | + DEF_HELPER_1_3(pfx ## subaddx, uint32_t, (uint32_t, uint32_t, uint32_t *)) | |
| 51 | + | |
| 52 | +PAS_OP(s) | |
| 53 | +PAS_OP(u) | |
| 54 | +#undef PAS_OP | |
| 55 | + | |
| 56 | +#define PAS_OP(pfx) \ | |
| 57 | + DEF_HELPER_1_2(pfx ## add8, uint32_t, (uint32_t, uint32_t)) \ | |
| 58 | + DEF_HELPER_1_2(pfx ## sub8, uint32_t, (uint32_t, uint32_t)) \ | |
| 59 | + DEF_HELPER_1_2(pfx ## sub16, uint32_t, (uint32_t, uint32_t)) \ | |
| 60 | + DEF_HELPER_1_2(pfx ## add16, uint32_t, (uint32_t, uint32_t)) \ | |
| 61 | + DEF_HELPER_1_2(pfx ## addsubx, uint32_t, (uint32_t, uint32_t)) \ | |
| 62 | + DEF_HELPER_1_2(pfx ## subaddx, uint32_t, (uint32_t, uint32_t)) | |
| 63 | +PAS_OP(q) | |
| 64 | +PAS_OP(sh) | |
| 65 | +PAS_OP(uq) | |
| 66 | +PAS_OP(uh) | |
| 67 | +#undef PAS_OP | |
| 68 | + | |
| 69 | +DEF_HELPER_1_2(ssat, uint32_t, (uint32_t, uint32_t)) | |
| 70 | +DEF_HELPER_1_2(usat, uint32_t, (uint32_t, uint32_t)) | |
| 71 | +DEF_HELPER_1_2(ssat16, uint32_t, (uint32_t, uint32_t)) | |
| 72 | +DEF_HELPER_1_2(usat16, uint32_t, (uint32_t, uint32_t)) | |
| 73 | + | |
| 74 | +DEF_HELPER_1_2(usad8, uint32_t, (uint32_t, uint32_t)) | |
| 75 | + | |
| 76 | +DEF_HELPER_1_3(sel_flags, uint32_t, (uint32_t, uint32_t, uint32_t)) | |
| 77 | + | |
| 36 | 78 | #undef DEF_HELPER |
| 37 | 79 | #undef DEF_HELPER_1_1 |
| 38 | 80 | #undef DEF_HELPER_1_2 | ... | ... |
target-arm/op.c
| ... | ... | @@ -805,327 +805,6 @@ void OPPROTO op_movl_user_T0(void) |
| 805 | 805 | FORCE_RET(); |
| 806 | 806 | } |
| 807 | 807 | |
| 808 | -/* ARMv6 Media instructions. */ | |
| 809 | - | |
| 810 | -/* Note that signed overflow is undefined in C. The following routines are | |
| 811 | - careful to use unsigned types where modulo arithmetic is required. | |
| 812 | - Failure to do so _will_ break on newer gcc. */ | |
| 813 | - | |
| 814 | -/* Signed saturating arithmetic. */ | |
| 815 | - | |
| 816 | -/* Perform 16-bit signed satruating addition. */ | |
| 817 | -static inline uint16_t add16_sat(uint16_t a, uint16_t b) | |
| 818 | -{ | |
| 819 | - uint16_t res; | |
| 820 | - | |
| 821 | - res = a + b; | |
| 822 | - if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) { | |
| 823 | - if (a & 0x8000) | |
| 824 | - res = 0x8000; | |
| 825 | - else | |
| 826 | - res = 0x7fff; | |
| 827 | - } | |
| 828 | - return res; | |
| 829 | -} | |
| 830 | - | |
| 831 | -/* Perform 8-bit signed satruating addition. */ | |
| 832 | -static inline uint8_t add8_sat(uint8_t a, uint8_t b) | |
| 833 | -{ | |
| 834 | - uint8_t res; | |
| 835 | - | |
| 836 | - res = a + b; | |
| 837 | - if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) { | |
| 838 | - if (a & 0x80) | |
| 839 | - res = 0x80; | |
| 840 | - else | |
| 841 | - res = 0x7f; | |
| 842 | - } | |
| 843 | - return res; | |
| 844 | -} | |
| 845 | - | |
| 846 | -/* Perform 16-bit signed satruating subtraction. */ | |
| 847 | -static inline uint16_t sub16_sat(uint16_t a, uint16_t b) | |
| 848 | -{ | |
| 849 | - uint16_t res; | |
| 850 | - | |
| 851 | - res = a - b; | |
| 852 | - if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) { | |
| 853 | - if (a & 0x8000) | |
| 854 | - res = 0x8000; | |
| 855 | - else | |
| 856 | - res = 0x7fff; | |
| 857 | - } | |
| 858 | - return res; | |
| 859 | -} | |
| 860 | - | |
| 861 | -/* Perform 8-bit signed satruating subtraction. */ | |
| 862 | -static inline uint8_t sub8_sat(uint8_t a, uint8_t b) | |
| 863 | -{ | |
| 864 | - uint8_t res; | |
| 865 | - | |
| 866 | - res = a - b; | |
| 867 | - if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) { | |
| 868 | - if (a & 0x80) | |
| 869 | - res = 0x80; | |
| 870 | - else | |
| 871 | - res = 0x7f; | |
| 872 | - } | |
| 873 | - return res; | |
| 874 | -} | |
| 875 | - | |
| 876 | -#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16); | |
| 877 | -#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16); | |
| 878 | -#define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8); | |
| 879 | -#define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8); | |
| 880 | -#define PFX q | |
| 881 | - | |
| 882 | -#include "op_addsub.h" | |
| 883 | - | |
| 884 | -/* Unsigned saturating arithmetic. */ | |
| 885 | -static inline uint16_t add16_usat(uint16_t a, uint8_t b) | |
| 886 | -{ | |
| 887 | - uint16_t res; | |
| 888 | - res = a + b; | |
| 889 | - if (res < a) | |
| 890 | - res = 0xffff; | |
| 891 | - return res; | |
| 892 | -} | |
| 893 | - | |
| 894 | -static inline uint16_t sub16_usat(uint16_t a, uint8_t b) | |
| 895 | -{ | |
| 896 | - if (a < b) | |
| 897 | - return a - b; | |
| 898 | - else | |
| 899 | - return 0; | |
| 900 | -} | |
| 901 | - | |
| 902 | -static inline uint8_t add8_usat(uint8_t a, uint8_t b) | |
| 903 | -{ | |
| 904 | - uint8_t res; | |
| 905 | - res = a + b; | |
| 906 | - if (res < a) | |
| 907 | - res = 0xff; | |
| 908 | - return res; | |
| 909 | -} | |
| 910 | - | |
| 911 | -static inline uint8_t sub8_usat(uint8_t a, uint8_t b) | |
| 912 | -{ | |
| 913 | - if (a < b) | |
| 914 | - return a - b; | |
| 915 | - else | |
| 916 | - return 0; | |
| 917 | -} | |
| 918 | - | |
| 919 | -#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16); | |
| 920 | -#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16); | |
| 921 | -#define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8); | |
| 922 | -#define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8); | |
| 923 | -#define PFX uq | |
| 924 | - | |
| 925 | -#include "op_addsub.h" | |
| 926 | - | |
| 927 | -/* Signed modulo arithmetic. */ | |
| 928 | -#define SARITH16(a, b, n, op) do { \ | |
| 929 | - int32_t sum; \ | |
| 930 | - sum = (int16_t)((uint16_t)(a) op (uint16_t)(b)); \ | |
| 931 | - RESULT(sum, n, 16); \ | |
| 932 | - if (sum >= 0) \ | |
| 933 | - ge |= 3 << (n * 2); \ | |
| 934 | - } while(0) | |
| 935 | - | |
| 936 | -#define SARITH8(a, b, n, op) do { \ | |
| 937 | - int32_t sum; \ | |
| 938 | - sum = (int8_t)((uint8_t)(a) op (uint8_t)(b)); \ | |
| 939 | - RESULT(sum, n, 8); \ | |
| 940 | - if (sum >= 0) \ | |
| 941 | - ge |= 1 << n; \ | |
| 942 | - } while(0) | |
| 943 | - | |
| 944 | - | |
| 945 | -#define ADD16(a, b, n) SARITH16(a, b, n, +) | |
| 946 | -#define SUB16(a, b, n) SARITH16(a, b, n, -) | |
| 947 | -#define ADD8(a, b, n) SARITH8(a, b, n, +) | |
| 948 | -#define SUB8(a, b, n) SARITH8(a, b, n, -) | |
| 949 | -#define PFX s | |
| 950 | -#define ARITH_GE | |
| 951 | - | |
| 952 | -#include "op_addsub.h" | |
| 953 | - | |
| 954 | -/* Unsigned modulo arithmetic. */ | |
| 955 | -#define ADD16(a, b, n) do { \ | |
| 956 | - uint32_t sum; \ | |
| 957 | - sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \ | |
| 958 | - RESULT(sum, n, 16); \ | |
| 959 | - if ((sum >> 16) == 0) \ | |
| 960 | - ge |= 3 << (n * 2); \ | |
| 961 | - } while(0) | |
| 962 | - | |
| 963 | -#define ADD8(a, b, n) do { \ | |
| 964 | - uint32_t sum; \ | |
| 965 | - sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \ | |
| 966 | - RESULT(sum, n, 8); \ | |
| 967 | - if ((sum >> 8) == 0) \ | |
| 968 | - ge |= 3 << (n * 2); \ | |
| 969 | - } while(0) | |
| 970 | - | |
| 971 | -#define SUB16(a, b, n) do { \ | |
| 972 | - uint32_t sum; \ | |
| 973 | - sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \ | |
| 974 | - RESULT(sum, n, 16); \ | |
| 975 | - if ((sum >> 16) == 0) \ | |
| 976 | - ge |= 3 << (n * 2); \ | |
| 977 | - } while(0) | |
| 978 | - | |
| 979 | -#define SUB8(a, b, n) do { \ | |
| 980 | - uint32_t sum; \ | |
| 981 | - sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \ | |
| 982 | - RESULT(sum, n, 8); \ | |
| 983 | - if ((sum >> 8) == 0) \ | |
| 984 | - ge |= 3 << (n * 2); \ | |
| 985 | - } while(0) | |
| 986 | - | |
| 987 | -#define PFX u | |
| 988 | -#define ARITH_GE | |
| 989 | - | |
| 990 | -#include "op_addsub.h" | |
| 991 | - | |
| 992 | -/* Halved signed arithmetic. */ | |
| 993 | -#define ADD16(a, b, n) \ | |
| 994 | - RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16) | |
| 995 | -#define SUB16(a, b, n) \ | |
| 996 | - RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16) | |
| 997 | -#define ADD8(a, b, n) \ | |
| 998 | - RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8) | |
| 999 | -#define SUB8(a, b, n) \ | |
| 1000 | - RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8) | |
| 1001 | -#define PFX sh | |
| 1002 | - | |
| 1003 | -#include "op_addsub.h" | |
| 1004 | - | |
| 1005 | -/* Halved unsigned arithmetic. */ | |
| 1006 | -#define ADD16(a, b, n) \ | |
| 1007 | - RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16) | |
| 1008 | -#define SUB16(a, b, n) \ | |
| 1009 | - RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16) | |
| 1010 | -#define ADD8(a, b, n) \ | |
| 1011 | - RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8) | |
| 1012 | -#define SUB8(a, b, n) \ | |
| 1013 | - RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8) | |
| 1014 | -#define PFX uh | |
| 1015 | - | |
| 1016 | -#include "op_addsub.h" | |
| 1017 | - | |
| 1018 | -void OPPROTO op_sel_T0_T1(void) | |
| 1019 | -{ | |
| 1020 | - uint32_t mask; | |
| 1021 | - uint32_t flags; | |
| 1022 | - | |
| 1023 | - flags = env->GE; | |
| 1024 | - mask = 0; | |
| 1025 | - if (flags & 1) | |
| 1026 | - mask |= 0xff; | |
| 1027 | - if (flags & 2) | |
| 1028 | - mask |= 0xff00; | |
| 1029 | - if (flags & 4) | |
| 1030 | - mask |= 0xff0000; | |
| 1031 | - if (flags & 8) | |
| 1032 | - mask |= 0xff000000; | |
| 1033 | - T0 = (T0 & mask) | (T1 & ~mask); | |
| 1034 | - FORCE_RET(); | |
| 1035 | -} | |
| 1036 | - | |
| 1037 | -/* Signed saturation. */ | |
| 1038 | -static inline uint32_t do_ssat(int32_t val, int shift) | |
| 1039 | -{ | |
| 1040 | - int32_t top; | |
| 1041 | - uint32_t mask; | |
| 1042 | - | |
| 1043 | - shift = PARAM1; | |
| 1044 | - top = val >> shift; | |
| 1045 | - mask = (1u << shift) - 1; | |
| 1046 | - if (top > 0) { | |
| 1047 | - env->QF = 1; | |
| 1048 | - return mask; | |
| 1049 | - } else if (top < -1) { | |
| 1050 | - env->QF = 1; | |
| 1051 | - return ~mask; | |
| 1052 | - } | |
| 1053 | - return val; | |
| 1054 | -} | |
| 1055 | - | |
| 1056 | -/* Unsigned saturation. */ | |
| 1057 | -static inline uint32_t do_usat(int32_t val, int shift) | |
| 1058 | -{ | |
| 1059 | - uint32_t max; | |
| 1060 | - | |
| 1061 | - shift = PARAM1; | |
| 1062 | - max = (1u << shift) - 1; | |
| 1063 | - if (val < 0) { | |
| 1064 | - env->QF = 1; | |
| 1065 | - return 0; | |
| 1066 | - } else if (val > max) { | |
| 1067 | - env->QF = 1; | |
| 1068 | - return max; | |
| 1069 | - } | |
| 1070 | - return val; | |
| 1071 | -} | |
| 1072 | - | |
| 1073 | -/* Signed saturate. */ | |
| 1074 | -void OPPROTO op_ssat_T1(void) | |
| 1075 | -{ | |
| 1076 | - T0 = do_ssat(T0, PARAM1); | |
| 1077 | - FORCE_RET(); | |
| 1078 | -} | |
| 1079 | - | |
| 1080 | -/* Dual halfword signed saturate. */ | |
| 1081 | -void OPPROTO op_ssat16_T1(void) | |
| 1082 | -{ | |
| 1083 | - uint32_t res; | |
| 1084 | - | |
| 1085 | - res = (uint16_t)do_ssat((int16_t)T0, PARAM1); | |
| 1086 | - res |= do_ssat(((int32_t)T0) >> 16, PARAM1) << 16; | |
| 1087 | - T0 = res; | |
| 1088 | - FORCE_RET(); | |
| 1089 | -} | |
| 1090 | - | |
| 1091 | -/* Unsigned saturate. */ | |
| 1092 | -void OPPROTO op_usat_T1(void) | |
| 1093 | -{ | |
| 1094 | - T0 = do_usat(T0, PARAM1); | |
| 1095 | - FORCE_RET(); | |
| 1096 | -} | |
| 1097 | - | |
| 1098 | -/* Dual halfword unsigned saturate. */ | |
| 1099 | -void OPPROTO op_usat16_T1(void) | |
| 1100 | -{ | |
| 1101 | - uint32_t res; | |
| 1102 | - | |
| 1103 | - res = (uint16_t)do_usat((int16_t)T0, PARAM1); | |
| 1104 | - res |= do_usat(((int32_t)T0) >> 16, PARAM1) << 16; | |
| 1105 | - T0 = res; | |
| 1106 | - FORCE_RET(); | |
| 1107 | -} | |
| 1108 | - | |
| 1109 | -/* Dual 16-bit add. */ | |
| 1110 | -static inline uint8_t do_usad(uint8_t a, uint8_t b) | |
| 1111 | -{ | |
| 1112 | - if (a > b) | |
| 1113 | - return a - b; | |
| 1114 | - else | |
| 1115 | - return b - a; | |
| 1116 | -} | |
| 1117 | - | |
| 1118 | -/* Unsigned sum of absolute byte differences. */ | |
| 1119 | -void OPPROTO op_usad8_T0_T1(void) | |
| 1120 | -{ | |
| 1121 | - uint32_t sum; | |
| 1122 | - sum = do_usad(T0, T1); | |
| 1123 | - sum += do_usad(T0 >> 8, T1 >> 8); | |
| 1124 | - sum += do_usad(T0 >> 16, T1 >>16); | |
| 1125 | - sum += do_usad(T0 >> 24, T1 >> 24); | |
| 1126 | - T0 = sum; | |
| 1127 | -} | |
| 1128 | - | |
| 1129 | 808 | void OPPROTO op_movl_T1_r13_banked(void) |
| 1130 | 809 | { |
| 1131 | 810 | T1 = helper_get_r13_banked(env, PARAM1); | ... | ... |
target-arm/op_addsub.h
| ... | ... | @@ -8,9 +8,11 @@ |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | #ifdef ARITH_GE |
| 11 | +#define GE_ARG , uint32_t *gep | |
| 11 | 12 | #define DECLARE_GE uint32_t ge = 0 |
| 12 | -#define SET_GE env->GE = ge | |
| 13 | +#define SET_GE *gep = ge | |
| 13 | 14 | #else |
| 15 | +#define GE_ARG | |
| 14 | 16 | #define DECLARE_GE do{}while(0) |
| 15 | 17 | #define SET_GE do{}while(0) |
| 16 | 18 | #endif |
| ... | ... | @@ -18,82 +20,77 @@ |
| 18 | 20 | #define RESULT(val, n, width) \ |
| 19 | 21 | res |= ((uint32_t)(glue(glue(uint,width),_t))(val)) << (n * width) |
| 20 | 22 | |
| 21 | -void OPPROTO glue(glue(op_,PFX),add16_T0_T1)(void) | |
| 23 | +uint32_t HELPER(glue(PFX,add16))(uint32_t a, uint32_t b GE_ARG) | |
| 22 | 24 | { |
| 23 | 25 | uint32_t res = 0; |
| 24 | 26 | DECLARE_GE; |
| 25 | 27 | |
| 26 | - ADD16(T0, T1, 0); | |
| 27 | - ADD16(T0 >> 16, T1 >> 16, 1); | |
| 28 | + ADD16(a, b, 0); | |
| 29 | + ADD16(a >> 16, b >> 16, 1); | |
| 28 | 30 | SET_GE; |
| 29 | - T0 = res; | |
| 30 | - FORCE_RET(); | |
| 31 | + return res; | |
| 31 | 32 | } |
| 32 | 33 | |
| 33 | -void OPPROTO glue(glue(op_,PFX),add8_T0_T1)(void) | |
| 34 | +uint32_t HELPER(glue(PFX,add8))(uint32_t a, uint32_t b GE_ARG) | |
| 34 | 35 | { |
| 35 | 36 | uint32_t res = 0; |
| 36 | 37 | DECLARE_GE; |
| 37 | 38 | |
| 38 | - ADD8(T0, T1, 0); | |
| 39 | - ADD8(T0 >> 8, T1 >> 8, 1); | |
| 40 | - ADD8(T0 >> 16, T1 >> 16, 2); | |
| 41 | - ADD8(T0 >> 24, T1 >> 24, 3); | |
| 39 | + ADD8(a, b, 0); | |
| 40 | + ADD8(a >> 8, b >> 8, 1); | |
| 41 | + ADD8(a >> 16, b >> 16, 2); | |
| 42 | + ADD8(a >> 24, b >> 24, 3); | |
| 42 | 43 | SET_GE; |
| 43 | - T0 = res; | |
| 44 | - FORCE_RET(); | |
| 44 | + return res; | |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | -void OPPROTO glue(glue(op_,PFX),sub16_T0_T1)(void) | |
| 47 | +uint32_t HELPER(glue(PFX,sub16))(uint32_t a, uint32_t b GE_ARG) | |
| 48 | 48 | { |
| 49 | 49 | uint32_t res = 0; |
| 50 | 50 | DECLARE_GE; |
| 51 | 51 | |
| 52 | - SUB16(T0, T1, 0); | |
| 53 | - SUB16(T0 >> 16, T1 >> 16, 1); | |
| 52 | + SUB16(a, b, 0); | |
| 53 | + SUB16(a >> 16, b >> 16, 1); | |
| 54 | 54 | SET_GE; |
| 55 | - T0 = res; | |
| 56 | - FORCE_RET(); | |
| 55 | + return res; | |
| 57 | 56 | } |
| 58 | 57 | |
| 59 | -void OPPROTO glue(glue(op_,PFX),sub8_T0_T1)(void) | |
| 58 | +uint32_t HELPER(glue(PFX,sub8))(uint32_t a, uint32_t b GE_ARG) | |
| 60 | 59 | { |
| 61 | 60 | uint32_t res = 0; |
| 62 | 61 | DECLARE_GE; |
| 63 | 62 | |
| 64 | - SUB8(T0, T1, 0); | |
| 65 | - SUB8(T0 >> 8, T1 >> 8, 1); | |
| 66 | - SUB8(T0 >> 16, T1 >> 16, 2); | |
| 67 | - SUB8(T0 >> 24, T1 >> 24, 3); | |
| 63 | + SUB8(a, b, 0); | |
| 64 | + SUB8(a >> 8, b >> 8, 1); | |
| 65 | + SUB8(a >> 16, b >> 16, 2); | |
| 66 | + SUB8(a >> 24, b >> 24, 3); | |
| 68 | 67 | SET_GE; |
| 69 | - T0 = res; | |
| 70 | - FORCE_RET(); | |
| 68 | + return res; | |
| 71 | 69 | } |
| 72 | 70 | |
| 73 | -void OPPROTO glue(glue(op_,PFX),subaddx_T0_T1)(void) | |
| 71 | +uint32_t HELPER(glue(PFX,subaddx))(uint32_t a, uint32_t b GE_ARG) | |
| 74 | 72 | { |
| 75 | 73 | uint32_t res = 0; |
| 76 | 74 | DECLARE_GE; |
| 77 | 75 | |
| 78 | - ADD16(T0, T1, 0); | |
| 79 | - SUB16(T0 >> 16, T1 >> 16, 1); | |
| 76 | + ADD16(a, b, 0); | |
| 77 | + SUB16(a >> 16, b >> 16, 1); | |
| 80 | 78 | SET_GE; |
| 81 | - T0 = res; | |
| 82 | - FORCE_RET(); | |
| 79 | + return res; | |
| 83 | 80 | } |
| 84 | 81 | |
| 85 | -void OPPROTO glue(glue(op_,PFX),addsubx_T0_T1)(void) | |
| 82 | +uint32_t HELPER(glue(PFX,addsubx))(uint32_t a, uint32_t b GE_ARG) | |
| 86 | 83 | { |
| 87 | 84 | uint32_t res = 0; |
| 88 | 85 | DECLARE_GE; |
| 89 | 86 | |
| 90 | - SUB16(T0, T1, 0); | |
| 91 | - ADD16(T0 >> 16, T1 >> 16, 1); | |
| 87 | + SUB16(a, b, 0); | |
| 88 | + ADD16(a >> 16, b >> 16, 1); | |
| 92 | 89 | SET_GE; |
| 93 | - T0 = res; | |
| 94 | - FORCE_RET(); | |
| 90 | + return res; | |
| 95 | 91 | } |
| 96 | 92 | |
| 93 | +#undef GE_ARG | |
| 97 | 94 | #undef DECLARE_GE |
| 98 | 95 | #undef SET_GE |
| 99 | 96 | #undef RESULT | ... | ... |
target-arm/op_helper.c
| ... | ... | @@ -369,3 +369,70 @@ uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b) |
| 369 | 369 | return res; |
| 370 | 370 | } |
| 371 | 371 | |
| 372 | +/* Signed saturation. */ | |
| 373 | +static inline uint32_t do_ssat(int32_t val, int shift) | |
| 374 | +{ | |
| 375 | + int32_t top; | |
| 376 | + uint32_t mask; | |
| 377 | + | |
| 378 | + shift = PARAM1; | |
| 379 | + top = val >> shift; | |
| 380 | + mask = (1u << shift) - 1; | |
| 381 | + if (top > 0) { | |
| 382 | + env->QF = 1; | |
| 383 | + return mask; | |
| 384 | + } else if (top < -1) { | |
| 385 | + env->QF = 1; | |
| 386 | + return ~mask; | |
| 387 | + } | |
| 388 | + return val; | |
| 389 | +} | |
| 390 | + | |
| 391 | +/* Unsigned saturation. */ | |
| 392 | +static inline uint32_t do_usat(int32_t val, int shift) | |
| 393 | +{ | |
| 394 | + uint32_t max; | |
| 395 | + | |
| 396 | + shift = PARAM1; | |
| 397 | + max = (1u << shift) - 1; | |
| 398 | + if (val < 0) { | |
| 399 | + env->QF = 1; | |
| 400 | + return 0; | |
| 401 | + } else if (val > max) { | |
| 402 | + env->QF = 1; | |
| 403 | + return max; | |
| 404 | + } | |
| 405 | + return val; | |
| 406 | +} | |
| 407 | + | |
| 408 | +/* Signed saturate. */ | |
| 409 | +uint32_t HELPER(ssat)(uint32_t x, uint32_t shift) | |
| 410 | +{ | |
| 411 | + return do_ssat(x, shift); | |
| 412 | +} | |
| 413 | + | |
| 414 | +/* Dual halfword signed saturate. */ | |
| 415 | +uint32_t HELPER(ssat16)(uint32_t x, uint32_t shift) | |
| 416 | +{ | |
| 417 | + uint32_t res; | |
| 418 | + | |
| 419 | + res = (uint16_t)do_ssat((int16_t)x, shift); | |
| 420 | + res |= do_ssat(((int32_t)x) >> 16, shift) << 16; | |
| 421 | + return res; | |
| 422 | +} | |
| 423 | + | |
| 424 | +/* Unsigned saturate. */ | |
| 425 | +uint32_t HELPER(usat)(uint32_t x, uint32_t shift) | |
| 426 | +{ | |
| 427 | + return do_usat(x, shift); | |
| 428 | +} | |
| 429 | + | |
| 430 | +/* Dual halfword unsigned saturate. */ | |
| 431 | +uint32_t HELPER(usat16)(uint32_t x, uint32_t shift) | |
| 432 | +{ | |
| 433 | + uint32_t res; | |
| 434 | + | |
| 435 | + res = (uint16_t)do_usat((int16_t)x, shift); | |
| 436 | + res |= do_usat(((int32_t)x) >> 16, shift) << 16; | |
| 437 | + return res; | |
| 438 | +} | ... | ... |
target-arm/translate.c
| ... | ... | @@ -226,7 +226,6 @@ static void gen_smul_dual(TCGv a, TCGv b) |
| 226 | 226 | { |
| 227 | 227 | TCGv tmp1 = new_tmp(); |
| 228 | 228 | TCGv tmp2 = new_tmp(); |
| 229 | - TCGv res; | |
| 230 | 229 | tcg_gen_ext8s_i32(tmp1, a); |
| 231 | 230 | tcg_gen_ext8s_i32(tmp2, b); |
| 232 | 231 | tcg_gen_mul_i32(tmp1, tmp1, tmp2); |
| ... | ... | @@ -495,49 +494,93 @@ static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) |
| 495 | 494 | } |
| 496 | 495 | }; |
| 497 | 496 | |
| 498 | -#define PAS_OP(pfx) { \ | |
| 499 | - gen_op_ ## pfx ## add16_T0_T1, \ | |
| 500 | - gen_op_ ## pfx ## addsubx_T0_T1, \ | |
| 501 | - gen_op_ ## pfx ## subaddx_T0_T1, \ | |
| 502 | - gen_op_ ## pfx ## sub16_T0_T1, \ | |
| 503 | - gen_op_ ## pfx ## add8_T0_T1, \ | |
| 504 | - NULL, \ | |
| 505 | - NULL, \ | |
| 506 | - gen_op_ ## pfx ## sub8_T0_T1 } | |
| 507 | - | |
| 508 | -static GenOpFunc *gen_arm_parallel_addsub[8][8] = { | |
| 509 | - {}, | |
| 510 | - PAS_OP(s), | |
| 511 | - PAS_OP(q), | |
| 512 | - PAS_OP(sh), | |
| 513 | - {}, | |
| 514 | - PAS_OP(u), | |
| 515 | - PAS_OP(uq), | |
| 516 | - PAS_OP(uh), | |
| 517 | -}; | |
| 497 | +#define PAS_OP(pfx) \ | |
| 498 | + switch (op2) { \ | |
| 499 | + case 0: gen_pas_helper(glue(pfx,add16)); break; \ | |
| 500 | + case 1: gen_pas_helper(glue(pfx,addsubx)); break; \ | |
| 501 | + case 2: gen_pas_helper(glue(pfx,subaddx)); break; \ | |
| 502 | + case 3: gen_pas_helper(glue(pfx,sub16)); break; \ | |
| 503 | + case 4: gen_pas_helper(glue(pfx,add8)); break; \ | |
| 504 | + case 7: gen_pas_helper(glue(pfx,sub8)); break; \ | |
| 505 | + } | |
| 506 | +void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b) | |
| 507 | +{ | |
| 508 | + TCGv tmp; | |
| 509 | + | |
| 510 | + switch (op1) { | |
| 511 | +#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp) | |
| 512 | + case 1: | |
| 513 | + tmp = tcg_temp_new(TCG_TYPE_PTR); | |
| 514 | + tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); | |
| 515 | + PAS_OP(s) | |
| 516 | + break; | |
| 517 | + case 5: | |
| 518 | + tmp = tcg_temp_new(TCG_TYPE_PTR); | |
| 519 | + tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); | |
| 520 | + PAS_OP(u) | |
| 521 | + break; | |
| 522 | +#undef gen_pas_helper | |
| 523 | +#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) | |
| 524 | + case 2: | |
| 525 | + PAS_OP(q); | |
| 526 | + break; | |
| 527 | + case 3: | |
| 528 | + PAS_OP(sh); | |
| 529 | + break; | |
| 530 | + case 6: | |
| 531 | + PAS_OP(uq); | |
| 532 | + break; | |
| 533 | + case 7: | |
| 534 | + PAS_OP(uh); | |
| 535 | + break; | |
| 536 | +#undef gen_pas_helper | |
| 537 | + } | |
| 538 | +} | |
| 518 | 539 | #undef PAS_OP |
| 519 | 540 | |
| 520 | -/* For unknown reasons Arm and Thumb-2 use arbitrarily diffenet encodings. */ | |
| 521 | -#define PAS_OP(pfx) { \ | |
| 522 | - gen_op_ ## pfx ## add8_T0_T1, \ | |
| 523 | - gen_op_ ## pfx ## add16_T0_T1, \ | |
| 524 | - gen_op_ ## pfx ## addsubx_T0_T1, \ | |
| 525 | - NULL, \ | |
| 526 | - gen_op_ ## pfx ## sub8_T0_T1, \ | |
| 527 | - gen_op_ ## pfx ## sub16_T0_T1, \ | |
| 528 | - gen_op_ ## pfx ## subaddx_T0_T1, \ | |
| 529 | - NULL } | |
| 530 | - | |
| 531 | -static GenOpFunc *gen_thumb2_parallel_addsub[8][8] = { | |
| 532 | - PAS_OP(s), | |
| 533 | - PAS_OP(q), | |
| 534 | - PAS_OP(sh), | |
| 535 | - {}, | |
| 536 | - PAS_OP(u), | |
| 537 | - PAS_OP(uq), | |
| 538 | - PAS_OP(uh), | |
| 539 | - {} | |
| 540 | -}; | |
| 541 | +/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */ | |
| 542 | +#define PAS_OP(pfx) \ | |
| 543 | + switch (op2) { \ | |
| 544 | + case 0: gen_pas_helper(glue(pfx,add8)); break; \ | |
| 545 | + case 1: gen_pas_helper(glue(pfx,add16)); break; \ | |
| 546 | + case 2: gen_pas_helper(glue(pfx,addsubx)); break; \ | |
| 547 | + case 4: gen_pas_helper(glue(pfx,sub8)); break; \ | |
| 548 | + case 5: gen_pas_helper(glue(pfx,sub16)); break; \ | |
| 549 | + case 6: gen_pas_helper(glue(pfx,subaddx)); break; \ | |
| 550 | + } | |
| 551 | +void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b) | |
| 552 | +{ | |
| 553 | + TCGv tmp; | |
| 554 | + | |
| 555 | + switch (op1) { | |
| 556 | +#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp) | |
| 557 | + case 0: | |
| 558 | + tmp = tcg_temp_new(TCG_TYPE_PTR); | |
| 559 | + tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); | |
| 560 | + PAS_OP(s) | |
| 561 | + break; | |
| 562 | + case 4: | |
| 563 | + tmp = tcg_temp_new(TCG_TYPE_PTR); | |
| 564 | + tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); | |
| 565 | + PAS_OP(u) | |
| 566 | + break; | |
| 567 | +#undef gen_pas_helper | |
| 568 | +#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) | |
| 569 | + case 1: | |
| 570 | + PAS_OP(q); | |
| 571 | + break; | |
| 572 | + case 2: | |
| 573 | + PAS_OP(sh); | |
| 574 | + break; | |
| 575 | + case 5: | |
| 576 | + PAS_OP(uq); | |
| 577 | + break; | |
| 578 | + case 6: | |
| 579 | + PAS_OP(uh); | |
| 580 | + break; | |
| 581 | +#undef gen_pas_helper | |
| 582 | + } | |
| 583 | +} | |
| 541 | 584 | #undef PAS_OP |
| 542 | 585 | |
| 543 | 586 | static GenOpFunc1 *gen_test_cc[14] = { |
| ... | ... | @@ -4906,6 +4949,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 4906 | 4949 | unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; |
| 4907 | 4950 | TCGv tmp; |
| 4908 | 4951 | TCGv tmp2; |
| 4952 | + TCGv tmp3; | |
| 4909 | 4953 | |
| 4910 | 4954 | insn = ldl_code(s->pc); |
| 4911 | 4955 | s->pc += 4; |
| ... | ... | @@ -5591,13 +5635,14 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5591 | 5635 | switch ((insn >> 23) & 3) { |
| 5592 | 5636 | case 0: /* Parallel add/subtract. */ |
| 5593 | 5637 | op1 = (insn >> 20) & 7; |
| 5594 | - gen_movl_T0_reg(s, rn); | |
| 5595 | - gen_movl_T1_reg(s, rm); | |
| 5638 | + tmp = load_reg(s, rn); | |
| 5639 | + tmp2 = load_reg(s, rm); | |
| 5596 | 5640 | sh = (insn >> 5) & 7; |
| 5597 | 5641 | if ((op1 & 3) == 0 || sh == 5 || sh == 6) |
| 5598 | 5642 | goto illegal_op; |
| 5599 | - gen_arm_parallel_addsub[op1][sh](); | |
| 5600 | - gen_movl_reg_T0(s, rd); | |
| 5643 | + gen_arm_parallel_addsub(op1, sh, tmp, tmp2); | |
| 5644 | + dead_tmp(tmp2); | |
| 5645 | + store_reg(s, rd, tmp); | |
| 5601 | 5646 | break; |
| 5602 | 5647 | case 1: |
| 5603 | 5648 | if ((insn & 0x00700020) == 0) { |
| ... | ... | @@ -5620,40 +5665,44 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5620 | 5665 | store_reg(s, rd, tmp); |
| 5621 | 5666 | } else if ((insn & 0x00200020) == 0x00200000) { |
| 5622 | 5667 | /* [us]sat */ |
| 5623 | - gen_movl_T1_reg(s, rm); | |
| 5668 | + tmp = load_reg(s, rm); | |
| 5624 | 5669 | shift = (insn >> 7) & 0x1f; |
| 5625 | 5670 | if (insn & (1 << 6)) { |
| 5626 | 5671 | if (shift == 0) |
| 5627 | 5672 | shift = 31; |
| 5628 | - gen_op_sarl_T1_im(shift); | |
| 5673 | + tcg_gen_sari_i32(tmp, tmp, shift); | |
| 5629 | 5674 | } else { |
| 5630 | - gen_op_shll_T1_im(shift); | |
| 5675 | + tcg_gen_shli_i32(tmp, tmp, shift); | |
| 5631 | 5676 | } |
| 5632 | 5677 | sh = (insn >> 16) & 0x1f; |
| 5633 | 5678 | if (sh != 0) { |
| 5634 | 5679 | if (insn & (1 << 22)) |
| 5635 | - gen_op_usat_T1(sh); | |
| 5680 | + gen_helper_usat(tmp, tmp, tcg_const_i32(sh)); | |
| 5636 | 5681 | else |
| 5637 | - gen_op_ssat_T1(sh); | |
| 5682 | + gen_helper_ssat(tmp, tmp, tcg_const_i32(sh)); | |
| 5638 | 5683 | } |
| 5639 | - gen_movl_T1_reg(s, rd); | |
| 5684 | + store_reg(s, rd, tmp); | |
| 5640 | 5685 | } else if ((insn & 0x00300fe0) == 0x00200f20) { |
| 5641 | 5686 | /* [us]sat16 */ |
| 5642 | - gen_movl_T1_reg(s, rm); | |
| 5687 | + tmp = load_reg(s, rm); | |
| 5643 | 5688 | sh = (insn >> 16) & 0x1f; |
| 5644 | 5689 | if (sh != 0) { |
| 5645 | 5690 | if (insn & (1 << 22)) |
| 5646 | - gen_op_usat16_T1(sh); | |
| 5691 | + gen_helper_usat16(tmp, tmp, tcg_const_i32(sh)); | |
| 5647 | 5692 | else |
| 5648 | - gen_op_ssat16_T1(sh); | |
| 5693 | + gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh)); | |
| 5649 | 5694 | } |
| 5650 | - gen_movl_T1_reg(s, rd); | |
| 5695 | + store_reg(s, rd, tmp); | |
| 5651 | 5696 | } else if ((insn & 0x00700fe0) == 0x00000fa0) { |
| 5652 | 5697 | /* Select bytes. */ |
| 5653 | - gen_movl_T0_reg(s, rn); | |
| 5654 | - gen_movl_T1_reg(s, rm); | |
| 5655 | - gen_op_sel_T0_T1(); | |
| 5656 | - gen_movl_reg_T0(s, rd); | |
| 5698 | + tmp = load_reg(s, rn); | |
| 5699 | + tmp2 = load_reg(s, rm); | |
| 5700 | + tmp3 = new_tmp(); | |
| 5701 | + tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE)); | |
| 5702 | + gen_helper_sel_flags(tmp, tmp3, tmp, tmp2); | |
| 5703 | + dead_tmp(tmp3); | |
| 5704 | + dead_tmp(tmp2); | |
| 5705 | + store_reg(s, rd, tmp); | |
| 5657 | 5706 | } else if ((insn & 0x000003e0) == 0x00000060) { |
| 5658 | 5707 | gen_movl_T1_reg(s, rm); |
| 5659 | 5708 | shift = (insn >> 10) & 3; |
| ... | ... | @@ -5755,15 +5804,17 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5755 | 5804 | op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7); |
| 5756 | 5805 | switch (op1) { |
| 5757 | 5806 | case 0: /* Unsigned sum of absolute differences. */ |
| 5758 | - goto illegal_op; | |
| 5759 | - gen_movl_T0_reg(s, rm); | |
| 5760 | - gen_movl_T1_reg(s, rs); | |
| 5761 | - gen_op_usad8_T0_T1(); | |
| 5807 | + ARCH(6); | |
| 5808 | + tmp = load_reg(s, rm); | |
| 5809 | + tmp2 = load_reg(s, rs); | |
| 5810 | + gen_helper_usad8(tmp, tmp, tmp2); | |
| 5811 | + dead_tmp(tmp2); | |
| 5762 | 5812 | if (rn != 15) { |
| 5763 | - gen_movl_T1_reg(s, rn); | |
| 5764 | - gen_op_addl_T0_T1(); | |
| 5813 | + tmp2 = load_reg(s, rn); | |
| 5814 | + tcg_gen_add_i32(tmp, tmp, tmp2); | |
| 5815 | + dead_tmp(tmp2); | |
| 5765 | 5816 | } |
| 5766 | - gen_movl_reg_T0(s, rd); | |
| 5817 | + store_reg(s, rd, tmp); | |
| 5767 | 5818 | break; |
| 5768 | 5819 | case 0x20: case 0x24: case 0x28: case 0x2c: |
| 5769 | 5820 | /* Bitfield insert/clear. */ |
| ... | ... | @@ -6120,6 +6171,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6120 | 6171 | uint32_t insn, imm, shift, offset, addr; |
| 6121 | 6172 | uint32_t rd, rn, rm, rs; |
| 6122 | 6173 | TCGv tmp; |
| 6174 | + TCGv tmp2; | |
| 6175 | + TCGv tmp3; | |
| 6123 | 6176 | int op; |
| 6124 | 6177 | int shiftop; |
| 6125 | 6178 | int conds; |
| ... | ... | @@ -6464,10 +6517,11 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6464 | 6517 | shift = (insn >> 4) & 7; |
| 6465 | 6518 | if ((op & 3) == 3 || (shift & 3) == 3) |
| 6466 | 6519 | goto illegal_op; |
| 6467 | - gen_movl_T0_reg(s, rn); | |
| 6468 | - gen_movl_T1_reg(s, rm); | |
| 6469 | - gen_thumb2_parallel_addsub[op][shift](); | |
| 6470 | - gen_movl_reg_T0(s, rd); | |
| 6520 | + tmp = load_reg(s, rn); | |
| 6521 | + tmp2 = load_reg(s, rm); | |
| 6522 | + gen_thumb2_parallel_addsub(op, shift, tmp, tmp2); | |
| 6523 | + dead_tmp(tmp2); | |
| 6524 | + store_reg(s, rd, tmp); | |
| 6471 | 6525 | break; |
| 6472 | 6526 | case 3: /* Other data processing. */ |
| 6473 | 6527 | op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7); |
| ... | ... | @@ -6498,7 +6552,10 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6498 | 6552 | break; |
| 6499 | 6553 | case 0x10: /* sel */ |
| 6500 | 6554 | gen_movl_T1_reg(s, rm); |
| 6501 | - gen_op_sel_T0_T1(); | |
| 6555 | + tmp3 = new_tmp(); | |
| 6556 | + tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE)); | |
| 6557 | + gen_helper_sel_flags(cpu_T[0], tmp3, cpu_T[0], cpu_T[1]); | |
| 6558 | + dead_tmp(tmp3); | |
| 6502 | 6559 | break; |
| 6503 | 6560 | case 0x18: /* clz */ |
| 6504 | 6561 | gen_helper_clz(cpu_T[0], cpu_T[0]); |
| ... | ... | @@ -6581,7 +6638,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6581 | 6638 | gen_movl_reg_T0(s, rd); |
| 6582 | 6639 | break; |
| 6583 | 6640 | case 7: /* Unsigned sum of absolute differences. */ |
| 6584 | - gen_op_usad8_T0_T1(); | |
| 6641 | + gen_helper_usad8(cpu_T[0], cpu_T[0], cpu_T[1]); | |
| 6585 | 6642 | if (rs != 15) { |
| 6586 | 6643 | gen_movl_T1_reg(s, rs); |
| 6587 | 6644 | gen_op_addl_T0_T1(); |
| ... | ... | @@ -6821,63 +6878,64 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6821 | 6878 | op = (insn >> 21) & 7; |
| 6822 | 6879 | imm = insn & 0x1f; |
| 6823 | 6880 | shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); |
| 6824 | - if (rn == 15) | |
| 6825 | - gen_op_movl_T1_im(0); | |
| 6826 | - else | |
| 6827 | - gen_movl_T1_reg(s, rn); | |
| 6881 | + if (rn == 15) { | |
| 6882 | + tmp = new_tmp(); | |
| 6883 | + tcg_gen_movi_i32(tmp, 0); | |
| 6884 | + } else { | |
| 6885 | + tmp = load_reg(s, rn); | |
| 6886 | + } | |
| 6828 | 6887 | switch (op) { |
| 6829 | 6888 | case 2: /* Signed bitfield extract. */ |
| 6830 | 6889 | imm++; |
| 6831 | 6890 | if (shift + imm > 32) |
| 6832 | 6891 | goto illegal_op; |
| 6833 | 6892 | if (imm < 32) |
| 6834 | - gen_sbfx(cpu_T[1], shift, imm); | |
| 6893 | + gen_sbfx(tmp, shift, imm); | |
| 6835 | 6894 | break; |
| 6836 | 6895 | case 6: /* Unsigned bitfield extract. */ |
| 6837 | 6896 | imm++; |
| 6838 | 6897 | if (shift + imm > 32) |
| 6839 | 6898 | goto illegal_op; |
| 6840 | 6899 | if (imm < 32) |
| 6841 | - gen_ubfx(cpu_T[1], shift, (1u << imm) - 1); | |
| 6900 | + gen_ubfx(tmp, shift, (1u << imm) - 1); | |
| 6842 | 6901 | break; |
| 6843 | 6902 | case 3: /* Bitfield insert/clear. */ |
| 6844 | 6903 | if (imm < shift) |
| 6845 | 6904 | goto illegal_op; |
| 6846 | 6905 | imm = imm + 1 - shift; |
| 6847 | 6906 | if (imm != 32) { |
| 6848 | - gen_movl_T0_reg(s, rd); | |
| 6849 | - gen_bfi(cpu_T[1], cpu_T[0], cpu_T[1], | |
| 6907 | + tmp2 = load_reg(s, rd); | |
| 6908 | + gen_bfi(tmp, tmp2, tmp, | |
| 6850 | 6909 | shift, ((1u << imm) - 1) << shift); |
| 6910 | + dead_tmp(tmp2); | |
| 6851 | 6911 | } |
| 6852 | 6912 | break; |
| 6853 | 6913 | case 7: |
| 6854 | 6914 | goto illegal_op; |
| 6855 | 6915 | default: /* Saturate. */ |
| 6856 | - gen_movl_T1_reg(s, rn); | |
| 6857 | 6916 | if (shift) { |
| 6858 | 6917 | if (op & 1) |
| 6859 | - gen_op_sarl_T1_im(shift); | |
| 6918 | + tcg_gen_sari_i32(tmp, tmp, shift); | |
| 6860 | 6919 | else |
| 6861 | - gen_op_shll_T1_im(shift); | |
| 6920 | + tcg_gen_shli_i32(tmp, tmp, shift); | |
| 6862 | 6921 | } |
| 6922 | + tmp2 = tcg_const_i32(imm); | |
| 6863 | 6923 | if (op & 4) { |
| 6864 | 6924 | /* Unsigned. */ |
| 6865 | - gen_op_ssat_T1(imm); | |
| 6866 | 6925 | if ((op & 1) && shift == 0) |
| 6867 | - gen_op_usat16_T1(imm); | |
| 6926 | + gen_helper_usat16(tmp, tmp, tmp2); | |
| 6868 | 6927 | else |
| 6869 | - gen_op_usat_T1(imm); | |
| 6928 | + gen_helper_usat(tmp, tmp, tmp2); | |
| 6870 | 6929 | } else { |
| 6871 | 6930 | /* Signed. */ |
| 6872 | - gen_op_ssat_T1(imm); | |
| 6873 | 6931 | if ((op & 1) && shift == 0) |
| 6874 | - gen_op_ssat16_T1(imm); | |
| 6932 | + gen_helper_ssat16(tmp, tmp, tmp2); | |
| 6875 | 6933 | else |
| 6876 | - gen_op_ssat_T1(imm); | |
| 6934 | + gen_helper_ssat(tmp, tmp, tmp2); | |
| 6877 | 6935 | } |
| 6878 | 6936 | break; |
| 6879 | 6937 | } |
| 6880 | - gen_movl_reg_T1(s, rd); | |
| 6938 | + store_reg(s, rd, tmp); | |
| 6881 | 6939 | } else { |
| 6882 | 6940 | imm = ((insn & 0x04000000) >> 15) |
| 6883 | 6941 | | ((insn & 0x7000) >> 4) | (insn & 0xff); | ... | ... |
tcg/tcg-op.h
| ... | ... | @@ -237,6 +237,18 @@ static inline void tcg_gen_helper_1_2(void *func, TCGv ret, |
| 237 | 237 | 1, &ret, 2, args); |
| 238 | 238 | } |
| 239 | 239 | |
| 240 | +static inline void tcg_gen_helper_1_3(void *func, TCGv ret, | |
| 241 | + TCGv arg1, TCGv arg2, TCGv arg3) | |
| 242 | +{ | |
| 243 | + TCGv args[3]; | |
| 244 | + args[0] = arg1; | |
| 245 | + args[1] = arg2; | |
| 246 | + args[2] = arg3; | |
| 247 | + tcg_gen_call(&tcg_ctx, | |
| 248 | + tcg_const_ptr((tcg_target_long)func), TCG_HELPER_CALL_FLAGS, | |
| 249 | + 1, &ret, 3, args); | |
| 250 | +} | |
| 251 | + | |
| 240 | 252 | static inline void tcg_gen_helper_1_4(void *func, TCGv ret, |
| 241 | 253 | TCGv arg1, TCGv arg2, TCGv arg3, |
| 242 | 254 | TCGv arg4) |
| ... | ... | @@ -1416,3 +1428,10 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index) |
| 1416 | 1428 | #define tcg_gen_ext_tl_i64 tcg_gen_ext_i32_i64 |
| 1417 | 1429 | #define tcg_const_tl tcg_const_i32 |
| 1418 | 1430 | #endif |
| 1431 | + | |
| 1432 | +#if TCG_TARGET_REG_BITS == 32 | |
| 1433 | +#define tcg_gen_addi_ptr tcg_gen_addi_i32 | |
| 1434 | +#else /* TCG_TARGET_REG_BITS == 32 */ | |
| 1435 | +#define tcg_gen_addi_ptr tcg_gen_addi_i64 | |
| 1436 | +#endif /* TCG_TARGET_REG_BITS != 32 */ | |
| 1437 | + | ... | ... |