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 | + | ... | ... |