Commit 214c465f86138aadd7f59f050a188d4362bd3ab8
1 parent
2b0233ab
Switch the standard multiplication instructions to TCG.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4740 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
166 additions
and
94 deletions
target-mips/exec.h
target-mips/helper.h
target-mips/op.c
| ... | ... | @@ -68,18 +68,6 @@ |
| 68 | 68 | |
| 69 | 69 | /* 64 bits arithmetic */ |
| 70 | 70 | #if TARGET_LONG_BITS > HOST_LONG_BITS |
| 71 | -void op_mult (void) | |
| 72 | -{ | |
| 73 | - CALL_FROM_TB0(do_mult); | |
| 74 | - FORCE_RET(); | |
| 75 | -} | |
| 76 | - | |
| 77 | -void op_multu (void) | |
| 78 | -{ | |
| 79 | - CALL_FROM_TB0(do_multu); | |
| 80 | - FORCE_RET(); | |
| 81 | -} | |
| 82 | - | |
| 83 | 71 | void op_madd (void) |
| 84 | 72 | { |
| 85 | 73 | CALL_FROM_TB0(do_madd); |
| ... | ... | @@ -214,54 +202,6 @@ static always_inline void set_HI_LOT0 (uint64_t HILO) |
| 214 | 202 | env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); |
| 215 | 203 | } |
| 216 | 204 | |
| 217 | -void op_mult (void) | |
| 218 | -{ | |
| 219 | - set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); | |
| 220 | - FORCE_RET(); | |
| 221 | -} | |
| 222 | - | |
| 223 | -void op_multu (void) | |
| 224 | -{ | |
| 225 | - set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); | |
| 226 | - FORCE_RET(); | |
| 227 | -} | |
| 228 | - | |
| 229 | -void op_madd (void) | |
| 230 | -{ | |
| 231 | - int64_t tmp; | |
| 232 | - | |
| 233 | - tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); | |
| 234 | - set_HILO((int64_t)get_HILO() + tmp); | |
| 235 | - FORCE_RET(); | |
| 236 | -} | |
| 237 | - | |
| 238 | -void op_maddu (void) | |
| 239 | -{ | |
| 240 | - uint64_t tmp; | |
| 241 | - | |
| 242 | - tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); | |
| 243 | - set_HILO(get_HILO() + tmp); | |
| 244 | - FORCE_RET(); | |
| 245 | -} | |
| 246 | - | |
| 247 | -void op_msub (void) | |
| 248 | -{ | |
| 249 | - int64_t tmp; | |
| 250 | - | |
| 251 | - tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); | |
| 252 | - set_HILO((int64_t)get_HILO() - tmp); | |
| 253 | - FORCE_RET(); | |
| 254 | -} | |
| 255 | - | |
| 256 | -void op_msubu (void) | |
| 257 | -{ | |
| 258 | - uint64_t tmp; | |
| 259 | - | |
| 260 | - tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); | |
| 261 | - set_HILO(get_HILO() - tmp); | |
| 262 | - FORCE_RET(); | |
| 263 | -} | |
| 264 | - | |
| 265 | 205 | /* Multiplication variants of the vr54xx. */ |
| 266 | 206 | void op_muls (void) |
| 267 | 207 | { |
| ... | ... | @@ -349,20 +289,6 @@ void op_mulshiu (void) |
| 349 | 289 | |
| 350 | 290 | #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */ |
| 351 | 291 | |
| 352 | -#if defined(TARGET_MIPS64) | |
| 353 | -void op_dmult (void) | |
| 354 | -{ | |
| 355 | - CALL_FROM_TB4(muls64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1); | |
| 356 | - FORCE_RET(); | |
| 357 | -} | |
| 358 | - | |
| 359 | -void op_dmultu (void) | |
| 360 | -{ | |
| 361 | - CALL_FROM_TB4(mulu64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1); | |
| 362 | - FORCE_RET(); | |
| 363 | -} | |
| 364 | -#endif | |
| 365 | - | |
| 366 | 292 | /* CP1 functions */ |
| 367 | 293 | #if 0 |
| 368 | 294 | # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env) | ... | ... |
target-mips/op_helper.c
| ... | ... | @@ -192,16 +192,6 @@ static always_inline void set_HI_LOT0 (uint64_t HILO) |
| 192 | 192 | env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | -void do_mult (void) | |
| 196 | -{ | |
| 197 | - set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); | |
| 198 | -} | |
| 199 | - | |
| 200 | -void do_multu (void) | |
| 201 | -{ | |
| 202 | - set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1); | |
| 203 | -} | |
| 204 | - | |
| 205 | 195 | void do_madd (void) |
| 206 | 196 | { |
| 207 | 197 | int64_t tmp; |
| ... | ... | @@ -306,6 +296,18 @@ void do_mulshiu (void) |
| 306 | 296 | } |
| 307 | 297 | #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */ |
| 308 | 298 | |
| 299 | +#ifdef TARGET_MIPS64 | |
| 300 | +void do_dmult (void) | |
| 301 | +{ | |
| 302 | + muls64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1); | |
| 303 | +} | |
| 304 | + | |
| 305 | +void do_dmultu (void) | |
| 306 | +{ | |
| 307 | + mulu64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1); | |
| 308 | +} | |
| 309 | +#endif | |
| 310 | + | |
| 309 | 311 | #ifdef CONFIG_USER_ONLY |
| 310 | 312 | void do_mfc0_random (void) |
| 311 | 313 | { | ... | ... |
target-mips/translate.c
| ... | ... | @@ -1941,11 +1941,47 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, |
| 1941 | 1941 | opn = "divu"; |
| 1942 | 1942 | break; |
| 1943 | 1943 | case OPC_MULT: |
| 1944 | - gen_op_mult(); | |
| 1944 | + { | |
| 1945 | + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); | |
| 1946 | + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); | |
| 1947 | + | |
| 1948 | + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); | |
| 1949 | + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); | |
| 1950 | + tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); | |
| 1951 | + tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); | |
| 1952 | + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 1953 | + tcg_temp_free(r_tmp2); | |
| 1954 | + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); | |
| 1955 | + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); | |
| 1956 | + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); | |
| 1957 | + tcg_temp_free(r_tmp1); | |
| 1958 | + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); | |
| 1959 | + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); | |
| 1960 | + gen_store_LO(cpu_T[0], 0); | |
| 1961 | + gen_store_HI(cpu_T[1], 0); | |
| 1962 | + } | |
| 1945 | 1963 | opn = "mult"; |
| 1946 | 1964 | break; |
| 1947 | 1965 | case OPC_MULTU: |
| 1948 | - gen_op_multu(); | |
| 1966 | + { | |
| 1967 | + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); | |
| 1968 | + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); | |
| 1969 | + | |
| 1970 | + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); | |
| 1971 | + tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); | |
| 1972 | + tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]); | |
| 1973 | + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]); | |
| 1974 | + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 1975 | + tcg_temp_free(r_tmp2); | |
| 1976 | + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); | |
| 1977 | + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); | |
| 1978 | + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); | |
| 1979 | + tcg_temp_free(r_tmp1); | |
| 1980 | + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); | |
| 1981 | + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); | |
| 1982 | + gen_store_LO(cpu_T[0], 0); | |
| 1983 | + gen_store_HI(cpu_T[1], 0); | |
| 1984 | + } | |
| 1949 | 1985 | opn = "multu"; |
| 1950 | 1986 | break; |
| 1951 | 1987 | #if defined(TARGET_MIPS64) |
| ... | ... | @@ -2003,28 +2039,136 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, |
| 2003 | 2039 | opn = "ddivu"; |
| 2004 | 2040 | break; |
| 2005 | 2041 | case OPC_DMULT: |
| 2006 | - gen_op_dmult(); | |
| 2042 | + tcg_gen_helper_0_0(do_dmult); | |
| 2007 | 2043 | opn = "dmult"; |
| 2008 | 2044 | break; |
| 2009 | 2045 | case OPC_DMULTU: |
| 2010 | - gen_op_dmultu(); | |
| 2046 | + tcg_gen_helper_0_0(do_dmultu); | |
| 2011 | 2047 | opn = "dmultu"; |
| 2012 | 2048 | break; |
| 2013 | 2049 | #endif |
| 2014 | 2050 | case OPC_MADD: |
| 2015 | - gen_op_madd(); | |
| 2051 | + { | |
| 2052 | + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); | |
| 2053 | + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); | |
| 2054 | + TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64); | |
| 2055 | + | |
| 2056 | + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); | |
| 2057 | + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); | |
| 2058 | + tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); | |
| 2059 | + tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); | |
| 2060 | + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 2061 | + gen_load_LO(cpu_T[0], 0); | |
| 2062 | + gen_load_HI(cpu_T[1], 0); | |
| 2063 | + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); | |
| 2064 | + tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); | |
| 2065 | + tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); | |
| 2066 | + tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); | |
| 2067 | + tcg_temp_free(r_tmp3); | |
| 2068 | + tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 2069 | + tcg_temp_free(r_tmp2); | |
| 2070 | + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); | |
| 2071 | + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); | |
| 2072 | + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); | |
| 2073 | + tcg_temp_free(r_tmp1); | |
| 2074 | + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); | |
| 2075 | + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); | |
| 2076 | + gen_store_LO(cpu_T[0], 0); | |
| 2077 | + gen_store_HI(cpu_T[1], 0); | |
| 2078 | + } | |
| 2016 | 2079 | opn = "madd"; |
| 2017 | 2080 | break; |
| 2018 | 2081 | case OPC_MADDU: |
| 2019 | - gen_op_maddu(); | |
| 2082 | + { | |
| 2083 | + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); | |
| 2084 | + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); | |
| 2085 | + TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64); | |
| 2086 | + | |
| 2087 | + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); | |
| 2088 | + tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); | |
| 2089 | + tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]); | |
| 2090 | + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]); | |
| 2091 | + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 2092 | + gen_load_LO(cpu_T[0], 0); | |
| 2093 | + gen_load_HI(cpu_T[1], 0); | |
| 2094 | + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); | |
| 2095 | + tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); | |
| 2096 | + tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); | |
| 2097 | + tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); | |
| 2098 | + tcg_temp_free(r_tmp3); | |
| 2099 | + tcg_gen_add_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 2100 | + tcg_temp_free(r_tmp2); | |
| 2101 | + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); | |
| 2102 | + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); | |
| 2103 | + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); | |
| 2104 | + tcg_temp_free(r_tmp1); | |
| 2105 | + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); | |
| 2106 | + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); | |
| 2107 | + gen_store_LO(cpu_T[0], 0); | |
| 2108 | + gen_store_HI(cpu_T[1], 0); | |
| 2109 | + } | |
| 2020 | 2110 | opn = "maddu"; |
| 2021 | 2111 | break; |
| 2022 | 2112 | case OPC_MSUB: |
| 2023 | - gen_op_msub(); | |
| 2113 | + { | |
| 2114 | + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); | |
| 2115 | + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); | |
| 2116 | + TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64); | |
| 2117 | + | |
| 2118 | + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); | |
| 2119 | + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); | |
| 2120 | + tcg_gen_ext_tl_i64(r_tmp1, cpu_T[0]); | |
| 2121 | + tcg_gen_ext_tl_i64(r_tmp2, cpu_T[1]); | |
| 2122 | + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 2123 | + gen_load_LO(cpu_T[0], 0); | |
| 2124 | + gen_load_HI(cpu_T[1], 0); | |
| 2125 | + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); | |
| 2126 | + tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); | |
| 2127 | + tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); | |
| 2128 | + tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); | |
| 2129 | + tcg_temp_free(r_tmp3); | |
| 2130 | + tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 2131 | + tcg_temp_free(r_tmp2); | |
| 2132 | + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); | |
| 2133 | + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); | |
| 2134 | + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); | |
| 2135 | + tcg_temp_free(r_tmp1); | |
| 2136 | + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); | |
| 2137 | + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); | |
| 2138 | + gen_store_LO(cpu_T[0], 0); | |
| 2139 | + gen_store_HI(cpu_T[1], 0); | |
| 2140 | + } | |
| 2024 | 2141 | opn = "msub"; |
| 2025 | 2142 | break; |
| 2026 | 2143 | case OPC_MSUBU: |
| 2027 | - gen_op_msubu(); | |
| 2144 | + { | |
| 2145 | + TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I64); | |
| 2146 | + TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); | |
| 2147 | + TCGv r_tmp3 = tcg_temp_new(TCG_TYPE_I64); | |
| 2148 | + | |
| 2149 | + tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]); | |
| 2150 | + tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]); | |
| 2151 | + tcg_gen_extu_tl_i64(r_tmp1, cpu_T[0]); | |
| 2152 | + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[1]); | |
| 2153 | + tcg_gen_mul_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 2154 | + gen_load_LO(cpu_T[0], 0); | |
| 2155 | + gen_load_HI(cpu_T[1], 0); | |
| 2156 | + tcg_gen_extu_tl_i64(r_tmp2, cpu_T[0]); | |
| 2157 | + tcg_gen_extu_tl_i64(r_tmp3, cpu_T[1]); | |
| 2158 | + tcg_gen_shli_i64(r_tmp3, r_tmp3, 32); | |
| 2159 | + tcg_gen_or_i64(r_tmp2, r_tmp2, r_tmp3); | |
| 2160 | + tcg_temp_free(r_tmp3); | |
| 2161 | + tcg_gen_sub_i64(r_tmp1, r_tmp1, r_tmp2); | |
| 2162 | + tcg_temp_free(r_tmp2); | |
| 2163 | + tcg_gen_trunc_i64_tl(cpu_T[0], r_tmp1); | |
| 2164 | + tcg_gen_shri_i64(r_tmp1, r_tmp1, 32); | |
| 2165 | + tcg_gen_trunc_i64_tl(cpu_T[1], r_tmp1); | |
| 2166 | + tcg_temp_free(r_tmp1); | |
| 2167 | + tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]); | |
| 2168 | + tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]); | |
| 2169 | + gen_store_LO(cpu_T[0], 0); | |
| 2170 | + gen_store_HI(cpu_T[1], 0); | |
| 2171 | + } | |
| 2028 | 2172 | opn = "msubu"; |
| 2029 | 2173 | break; |
| 2030 | 2174 | default: | ... | ... |