Commit fbcc68286a427fe75e7af98d28dee92c71ba0cb5
1 parent
923617a3
Implement FP madd/msub, wire up bc1any[24][ft].
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2802 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
140 additions
and
12 deletions
target-mips/op.c
| ... | ... | @@ -2185,6 +2185,7 @@ FLOAT_OP(name, d) \ |
| 2185 | 2185 | FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ |
| 2186 | 2186 | update_fcr31(); \ |
| 2187 | 2187 | DEBUG_FPU_STATE(); \ |
| 2188 | + RETURN(); \ | |
| 2188 | 2189 | } \ |
| 2189 | 2190 | FLOAT_OP(name, s) \ |
| 2190 | 2191 | { \ |
| ... | ... | @@ -2192,6 +2193,7 @@ FLOAT_OP(name, s) \ |
| 2192 | 2193 | FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
| 2193 | 2194 | update_fcr31(); \ |
| 2194 | 2195 | DEBUG_FPU_STATE(); \ |
| 2196 | + RETURN(); \ | |
| 2195 | 2197 | } \ |
| 2196 | 2198 | FLOAT_OP(name, ps) \ |
| 2197 | 2199 | { \ |
| ... | ... | @@ -2200,6 +2202,7 @@ FLOAT_OP(name, ps) \ |
| 2200 | 2202 | FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \ |
| 2201 | 2203 | update_fcr31(); \ |
| 2202 | 2204 | DEBUG_FPU_STATE(); \ |
| 2205 | + RETURN(); \ | |
| 2203 | 2206 | } |
| 2204 | 2207 | FLOAT_BINOP(add) |
| 2205 | 2208 | FLOAT_BINOP(sub) |
| ... | ... | @@ -2207,6 +2210,16 @@ FLOAT_BINOP(mul) |
| 2207 | 2210 | FLOAT_BINOP(div) |
| 2208 | 2211 | #undef FLOAT_BINOP |
| 2209 | 2212 | |
| 2213 | +FLOAT_OP(addr, ps) | |
| 2214 | +{ | |
| 2215 | + set_float_exception_flags(0, &env->fp_status); | |
| 2216 | + FST2 = float32_add (FST0, FSTH0, &env->fp_status); | |
| 2217 | + FSTH2 = float32_add (FST1, FSTH1, &env->fp_status); | |
| 2218 | + update_fcr31(); | |
| 2219 | + DEBUG_FPU_STATE(); | |
| 2220 | + RETURN(); | |
| 2221 | +} | |
| 2222 | + | |
| 2210 | 2223 | /* ternary operations */ |
| 2211 | 2224 | #define FLOAT_TERNOP(name1, name2) \ |
| 2212 | 2225 | FLOAT_OP(name1 ## name2, d) \ |
| ... | ... | @@ -2214,12 +2227,14 @@ FLOAT_OP(name1 ## name2, d) \ |
| 2214 | 2227 | FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \ |
| 2215 | 2228 | FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \ |
| 2216 | 2229 | DEBUG_FPU_STATE(); \ |
| 2230 | + RETURN(); \ | |
| 2217 | 2231 | } \ |
| 2218 | 2232 | FLOAT_OP(name1 ## name2, s) \ |
| 2219 | 2233 | { \ |
| 2220 | 2234 | FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ |
| 2221 | 2235 | FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ |
| 2222 | 2236 | DEBUG_FPU_STATE(); \ |
| 2237 | + RETURN(); \ | |
| 2223 | 2238 | } \ |
| 2224 | 2239 | FLOAT_OP(name1 ## name2, ps) \ |
| 2225 | 2240 | { \ |
| ... | ... | @@ -2228,28 +2243,65 @@ FLOAT_OP(name1 ## name2, ps) \ |
| 2228 | 2243 | FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ |
| 2229 | 2244 | FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \ |
| 2230 | 2245 | DEBUG_FPU_STATE(); \ |
| 2246 | + RETURN(); \ | |
| 2231 | 2247 | } |
| 2232 | 2248 | FLOAT_TERNOP(mul, add) |
| 2233 | 2249 | FLOAT_TERNOP(mul, sub) |
| 2234 | 2250 | #undef FLOAT_TERNOP |
| 2235 | 2251 | |
| 2252 | +/* negated ternary operations */ | |
| 2253 | +#define FLOAT_NTERNOP(name1, name2) \ | |
| 2254 | +FLOAT_OP(n ## name1 ## name2, d) \ | |
| 2255 | +{ \ | |
| 2256 | + FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \ | |
| 2257 | + FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \ | |
| 2258 | + FDT2 ^= 1ULL << 63; \ | |
| 2259 | + DEBUG_FPU_STATE(); \ | |
| 2260 | + RETURN(); \ | |
| 2261 | +} \ | |
| 2262 | +FLOAT_OP(n ## name1 ## name2, s) \ | |
| 2263 | +{ \ | |
| 2264 | + FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ | |
| 2265 | + FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ | |
| 2266 | + FST2 ^= 1 << 31; \ | |
| 2267 | + DEBUG_FPU_STATE(); \ | |
| 2268 | + RETURN(); \ | |
| 2269 | +} \ | |
| 2270 | +FLOAT_OP(n ## name1 ## name2, ps) \ | |
| 2271 | +{ \ | |
| 2272 | + FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ | |
| 2273 | + FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \ | |
| 2274 | + FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ | |
| 2275 | + FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \ | |
| 2276 | + FST2 ^= 1 << 31; \ | |
| 2277 | + FSTH2 ^= 1 << 31; \ | |
| 2278 | + DEBUG_FPU_STATE(); \ | |
| 2279 | + RETURN(); \ | |
| 2280 | +} | |
| 2281 | +FLOAT_NTERNOP(mul, add) | |
| 2282 | +FLOAT_NTERNOP(mul, sub) | |
| 2283 | +#undef FLOAT_NTERNOP | |
| 2284 | + | |
| 2236 | 2285 | /* unary operations, modifying fp status */ |
| 2237 | 2286 | #define FLOAT_UNOP(name) \ |
| 2238 | 2287 | FLOAT_OP(name, d) \ |
| 2239 | 2288 | { \ |
| 2240 | 2289 | FDT2 = float64_ ## name(FDT0, &env->fp_status); \ |
| 2241 | 2290 | DEBUG_FPU_STATE(); \ |
| 2291 | + RETURN(); \ | |
| 2242 | 2292 | } \ |
| 2243 | 2293 | FLOAT_OP(name, s) \ |
| 2244 | 2294 | { \ |
| 2245 | 2295 | FST2 = float32_ ## name(FST0, &env->fp_status); \ |
| 2246 | 2296 | DEBUG_FPU_STATE(); \ |
| 2297 | + RETURN(); \ | |
| 2247 | 2298 | } \ |
| 2248 | 2299 | FLOAT_OP(name, ps) \ |
| 2249 | 2300 | { \ |
| 2250 | 2301 | FST2 = float32_ ## name(FST0, &env->fp_status); \ |
| 2251 | 2302 | FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \ |
| 2252 | 2303 | DEBUG_FPU_STATE(); \ |
| 2304 | + RETURN(); \ | |
| 2253 | 2305 | } |
| 2254 | 2306 | FLOAT_UNOP(sqrt) |
| 2255 | 2307 | #undef FLOAT_UNOP |
| ... | ... | @@ -2260,17 +2312,20 @@ FLOAT_OP(name, d) \ |
| 2260 | 2312 | { \ |
| 2261 | 2313 | FDT2 = float64_ ## name(FDT0); \ |
| 2262 | 2314 | DEBUG_FPU_STATE(); \ |
| 2315 | + RETURN(); \ | |
| 2263 | 2316 | } \ |
| 2264 | 2317 | FLOAT_OP(name, s) \ |
| 2265 | 2318 | { \ |
| 2266 | 2319 | FST2 = float32_ ## name(FST0); \ |
| 2267 | 2320 | DEBUG_FPU_STATE(); \ |
| 2321 | + RETURN(); \ | |
| 2268 | 2322 | } \ |
| 2269 | 2323 | FLOAT_OP(name, ps) \ |
| 2270 | 2324 | { \ |
| 2271 | 2325 | FST2 = float32_ ## name(FST0); \ |
| 2272 | 2326 | FSTH2 = float32_ ## name(FSTH0); \ |
| 2273 | 2327 | DEBUG_FPU_STATE(); \ |
| 2328 | + RETURN(); \ | |
| 2274 | 2329 | } |
| 2275 | 2330 | FLOAT_UNOP(abs) |
| 2276 | 2331 | FLOAT_UNOP(chs) | ... | ... |
target-mips/translate.c
| ... | ... | @@ -402,7 +402,7 @@ enum { |
| 402 | 402 | OPC_MSUB_D = 0x29 | OPC_CP3, |
| 403 | 403 | OPC_MSUB_PS = 0x2E | OPC_CP3, |
| 404 | 404 | OPC_NMADD_S = 0x30 | OPC_CP3, |
| 405 | - OPC_NMADD_D = 0x32 | OPC_CP3, | |
| 405 | + OPC_NMADD_D = 0x31 | OPC_CP3, | |
| 406 | 406 | OPC_NMADD_PS= 0x36 | OPC_CP3, |
| 407 | 407 | OPC_NMSUB_S = 0x38 | OPC_CP3, |
| 408 | 408 | OPC_NMSUB_D = 0x39 | OPC_CP3, |
| ... | ... | @@ -4955,6 +4955,17 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4955 | 4955 | GEN_STORE_FTN_FREG(fd, WTH2); |
| 4956 | 4956 | opn = "movn.ps"; |
| 4957 | 4957 | break; |
| 4958 | + case FOP(24, 22): | |
| 4959 | + CHECK_FR(ctx, fs | fd | ft); | |
| 4960 | + GEN_LOAD_FREG_FTN(WT0, fs); | |
| 4961 | + GEN_LOAD_FREG_FTN(WTH0, fs); | |
| 4962 | + GEN_LOAD_FREG_FTN(WT1, ft); | |
| 4963 | + GEN_LOAD_FREG_FTN(WTH1, ft); | |
| 4964 | + gen_op_float_addr_ps(); | |
| 4965 | + GEN_STORE_FTN_FREG(fd, WT2); | |
| 4966 | + GEN_STORE_FTN_FREG(fd, WTH2); | |
| 4967 | + opn = "addr.ps"; | |
| 4968 | + break; | |
| 4958 | 4969 | case FOP(32, 22): |
| 4959 | 4970 | CHECK_FR(ctx, fs); |
| 4960 | 4971 | GEN_LOAD_FREG_FTN(WTH0, fs); |
| ... | ... | @@ -5120,47 +5131,107 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd, |
| 5120 | 5131 | opn = "madd.s"; |
| 5121 | 5132 | break; |
| 5122 | 5133 | case OPC_MADD_D: |
| 5123 | - generate_exception (ctx, EXCP_RI); | |
| 5134 | + GEN_LOAD_FREG_FTN(DT0, fs); | |
| 5135 | + GEN_LOAD_FREG_FTN(DT1, ft); | |
| 5136 | + GEN_LOAD_FREG_FTN(DT2, fr); | |
| 5137 | + gen_op_float_muladd_d(); | |
| 5138 | + GEN_STORE_FTN_FREG(fd, DT2); | |
| 5124 | 5139 | opn = "madd.d"; |
| 5125 | 5140 | break; |
| 5126 | 5141 | case OPC_MADD_PS: |
| 5127 | - generate_exception (ctx, EXCP_RI); | |
| 5142 | + GEN_LOAD_FREG_FTN(WT0, fs); | |
| 5143 | + GEN_LOAD_FREG_FTN(WTH0, fs); | |
| 5144 | + GEN_LOAD_FREG_FTN(WT1, ft); | |
| 5145 | + GEN_LOAD_FREG_FTN(WTH1, ft); | |
| 5146 | + GEN_LOAD_FREG_FTN(WT2, fr); | |
| 5147 | + GEN_LOAD_FREG_FTN(WTH2, fr); | |
| 5148 | + gen_op_float_muladd_ps(); | |
| 5149 | + GEN_STORE_FTN_FREG(fd, WT2); | |
| 5150 | + GEN_STORE_FTN_FREG(fd, WTH2); | |
| 5128 | 5151 | opn = "madd.ps"; |
| 5129 | 5152 | break; |
| 5130 | 5153 | case OPC_MSUB_S: |
| 5131 | - generate_exception (ctx, EXCP_RI); | |
| 5154 | + GEN_LOAD_FREG_FTN(WT0, fs); | |
| 5155 | + GEN_LOAD_FREG_FTN(WT1, ft); | |
| 5156 | + GEN_LOAD_FREG_FTN(WT2, fr); | |
| 5157 | + gen_op_float_mulsub_s(); | |
| 5158 | + GEN_STORE_FTN_FREG(fd, WT2); | |
| 5132 | 5159 | opn = "msub.s"; |
| 5133 | 5160 | break; |
| 5134 | 5161 | case OPC_MSUB_D: |
| 5135 | - generate_exception (ctx, EXCP_RI); | |
| 5162 | + GEN_LOAD_FREG_FTN(DT0, fs); | |
| 5163 | + GEN_LOAD_FREG_FTN(DT1, ft); | |
| 5164 | + GEN_LOAD_FREG_FTN(DT2, fr); | |
| 5165 | + gen_op_float_mulsub_d(); | |
| 5166 | + GEN_STORE_FTN_FREG(fd, DT2); | |
| 5136 | 5167 | opn = "msub.d"; |
| 5137 | 5168 | break; |
| 5138 | 5169 | case OPC_MSUB_PS: |
| 5139 | - generate_exception (ctx, EXCP_RI); | |
| 5170 | + GEN_LOAD_FREG_FTN(WT0, fs); | |
| 5171 | + GEN_LOAD_FREG_FTN(WTH0, fs); | |
| 5172 | + GEN_LOAD_FREG_FTN(WT1, ft); | |
| 5173 | + GEN_LOAD_FREG_FTN(WTH1, ft); | |
| 5174 | + GEN_LOAD_FREG_FTN(WT2, fr); | |
| 5175 | + GEN_LOAD_FREG_FTN(WTH2, fr); | |
| 5176 | + gen_op_float_mulsub_ps(); | |
| 5177 | + GEN_STORE_FTN_FREG(fd, WT2); | |
| 5178 | + GEN_STORE_FTN_FREG(fd, WTH2); | |
| 5140 | 5179 | opn = "msub.ps"; |
| 5141 | 5180 | break; |
| 5142 | 5181 | case OPC_NMADD_S: |
| 5143 | - generate_exception (ctx, EXCP_RI); | |
| 5182 | + GEN_LOAD_FREG_FTN(WT0, fs); | |
| 5183 | + GEN_LOAD_FREG_FTN(WT1, ft); | |
| 5184 | + GEN_LOAD_FREG_FTN(WT2, fr); | |
| 5185 | + gen_op_float_nmuladd_s(); | |
| 5186 | + GEN_STORE_FTN_FREG(fd, WT2); | |
| 5144 | 5187 | opn = "nmadd.s"; |
| 5145 | 5188 | break; |
| 5146 | 5189 | case OPC_NMADD_D: |
| 5147 | - generate_exception (ctx, EXCP_RI); | |
| 5190 | + GEN_LOAD_FREG_FTN(DT0, fs); | |
| 5191 | + GEN_LOAD_FREG_FTN(DT1, ft); | |
| 5192 | + GEN_LOAD_FREG_FTN(DT2, fr); | |
| 5193 | + gen_op_float_nmuladd_d(); | |
| 5194 | + GEN_STORE_FTN_FREG(fd, DT2); | |
| 5148 | 5195 | opn = "nmadd.d"; |
| 5149 | 5196 | break; |
| 5150 | 5197 | case OPC_NMADD_PS: |
| 5151 | - generate_exception (ctx, EXCP_RI); | |
| 5198 | + GEN_LOAD_FREG_FTN(WT0, fs); | |
| 5199 | + GEN_LOAD_FREG_FTN(WTH0, fs); | |
| 5200 | + GEN_LOAD_FREG_FTN(WT1, ft); | |
| 5201 | + GEN_LOAD_FREG_FTN(WTH1, ft); | |
| 5202 | + GEN_LOAD_FREG_FTN(WT2, fr); | |
| 5203 | + GEN_LOAD_FREG_FTN(WTH2, fr); | |
| 5204 | + gen_op_float_nmuladd_ps(); | |
| 5205 | + GEN_STORE_FTN_FREG(fd, WT2); | |
| 5206 | + GEN_STORE_FTN_FREG(fd, WTH2); | |
| 5152 | 5207 | opn = "nmadd.ps"; |
| 5153 | 5208 | break; |
| 5154 | 5209 | case OPC_NMSUB_S: |
| 5155 | - generate_exception (ctx, EXCP_RI); | |
| 5210 | + GEN_LOAD_FREG_FTN(WT0, fs); | |
| 5211 | + GEN_LOAD_FREG_FTN(WT1, ft); | |
| 5212 | + GEN_LOAD_FREG_FTN(WT2, fr); | |
| 5213 | + gen_op_float_nmulsub_s(); | |
| 5214 | + GEN_STORE_FTN_FREG(fd, WT2); | |
| 5156 | 5215 | opn = "nmsub.s"; |
| 5157 | 5216 | break; |
| 5158 | 5217 | case OPC_NMSUB_D: |
| 5159 | - generate_exception (ctx, EXCP_RI); | |
| 5218 | + GEN_LOAD_FREG_FTN(DT0, fs); | |
| 5219 | + GEN_LOAD_FREG_FTN(DT1, ft); | |
| 5220 | + GEN_LOAD_FREG_FTN(DT2, fr); | |
| 5221 | + gen_op_float_nmulsub_d(); | |
| 5222 | + GEN_STORE_FTN_FREG(fd, DT2); | |
| 5160 | 5223 | opn = "nmsub.d"; |
| 5161 | 5224 | break; |
| 5162 | 5225 | case OPC_NMSUB_PS: |
| 5163 | - generate_exception (ctx, EXCP_RI); | |
| 5226 | + GEN_LOAD_FREG_FTN(WT0, fs); | |
| 5227 | + GEN_LOAD_FREG_FTN(WTH0, fs); | |
| 5228 | + GEN_LOAD_FREG_FTN(WT1, ft); | |
| 5229 | + GEN_LOAD_FREG_FTN(WTH1, ft); | |
| 5230 | + GEN_LOAD_FREG_FTN(WT2, fr); | |
| 5231 | + GEN_LOAD_FREG_FTN(WTH2, fr); | |
| 5232 | + gen_op_float_nmulsub_ps(); | |
| 5233 | + GEN_STORE_FTN_FREG(fd, WT2); | |
| 5234 | + GEN_STORE_FTN_FREG(fd, WTH2); | |
| 5164 | 5235 | opn = "nmsub.ps"; |
| 5165 | 5236 | break; |
| 5166 | 5237 | default: |
| ... | ... | @@ -5562,6 +5633,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
| 5562 | 5633 | gen_cp1(ctx, op1, rt, rd); |
| 5563 | 5634 | break; |
| 5564 | 5635 | case OPC_BC1: |
| 5636 | + case OPC_BC1ANY2: | |
| 5637 | + case OPC_BC1ANY4: | |
| 5565 | 5638 | gen_compute_branch1(ctx, MASK_BC1(ctx->opcode), |
| 5566 | 5639 | (rt >> 2) & 0x7, imm << 2); |
| 5567 | 5640 | return; | ... | ... |