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