Commit fbcc68286a427fe75e7af98d28dee92c71ba0cb5

Authored by ths
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
target-mips/op.c
@@ -2185,6 +2185,7 @@ FLOAT_OP(name, d) \ @@ -2185,6 +2185,7 @@ FLOAT_OP(name, d) \
2185 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ 2185 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
2186 update_fcr31(); \ 2186 update_fcr31(); \
2187 DEBUG_FPU_STATE(); \ 2187 DEBUG_FPU_STATE(); \
  2188 + RETURN(); \
2188 } \ 2189 } \
2189 FLOAT_OP(name, s) \ 2190 FLOAT_OP(name, s) \
2190 { \ 2191 { \
@@ -2192,6 +2193,7 @@ FLOAT_OP(name, s) \ @@ -2192,6 +2193,7 @@ FLOAT_OP(name, s) \
2192 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ 2193 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
2193 update_fcr31(); \ 2194 update_fcr31(); \
2194 DEBUG_FPU_STATE(); \ 2195 DEBUG_FPU_STATE(); \
  2196 + RETURN(); \
2195 } \ 2197 } \
2196 FLOAT_OP(name, ps) \ 2198 FLOAT_OP(name, ps) \
2197 { \ 2199 { \
@@ -2200,6 +2202,7 @@ FLOAT_OP(name, ps) \ @@ -2200,6 +2202,7 @@ FLOAT_OP(name, ps) \
2200 FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \ 2202 FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
2201 update_fcr31(); \ 2203 update_fcr31(); \
2202 DEBUG_FPU_STATE(); \ 2204 DEBUG_FPU_STATE(); \
  2205 + RETURN(); \
2203 } 2206 }
2204 FLOAT_BINOP(add) 2207 FLOAT_BINOP(add)
2205 FLOAT_BINOP(sub) 2208 FLOAT_BINOP(sub)
@@ -2207,6 +2210,16 @@ FLOAT_BINOP(mul) @@ -2207,6 +2210,16 @@ FLOAT_BINOP(mul)
2207 FLOAT_BINOP(div) 2210 FLOAT_BINOP(div)
2208 #undef FLOAT_BINOP 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 /* ternary operations */ 2223 /* ternary operations */
2211 #define FLOAT_TERNOP(name1, name2) \ 2224 #define FLOAT_TERNOP(name1, name2) \
2212 FLOAT_OP(name1 ## name2, d) \ 2225 FLOAT_OP(name1 ## name2, d) \
@@ -2214,12 +2227,14 @@ FLOAT_OP(name1 ## name2, d) \ @@ -2214,12 +2227,14 @@ FLOAT_OP(name1 ## name2, d) \
2214 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \ 2227 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
2215 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \ 2228 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
2216 DEBUG_FPU_STATE(); \ 2229 DEBUG_FPU_STATE(); \
  2230 + RETURN(); \
2217 } \ 2231 } \
2218 FLOAT_OP(name1 ## name2, s) \ 2232 FLOAT_OP(name1 ## name2, s) \
2219 { \ 2233 { \
2220 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \ 2234 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2221 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ 2235 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2222 DEBUG_FPU_STATE(); \ 2236 DEBUG_FPU_STATE(); \
  2237 + RETURN(); \
2223 } \ 2238 } \
2224 FLOAT_OP(name1 ## name2, ps) \ 2239 FLOAT_OP(name1 ## name2, ps) \
2225 { \ 2240 { \
@@ -2228,28 +2243,65 @@ FLOAT_OP(name1 ## name2, ps) \ @@ -2228,28 +2243,65 @@ FLOAT_OP(name1 ## name2, ps) \
2228 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \ 2243 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2229 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \ 2244 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2230 DEBUG_FPU_STATE(); \ 2245 DEBUG_FPU_STATE(); \
  2246 + RETURN(); \
2231 } 2247 }
2232 FLOAT_TERNOP(mul, add) 2248 FLOAT_TERNOP(mul, add)
2233 FLOAT_TERNOP(mul, sub) 2249 FLOAT_TERNOP(mul, sub)
2234 #undef FLOAT_TERNOP 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 /* unary operations, modifying fp status */ 2285 /* unary operations, modifying fp status */
2237 #define FLOAT_UNOP(name) \ 2286 #define FLOAT_UNOP(name) \
2238 FLOAT_OP(name, d) \ 2287 FLOAT_OP(name, d) \
2239 { \ 2288 { \
2240 FDT2 = float64_ ## name(FDT0, &env->fp_status); \ 2289 FDT2 = float64_ ## name(FDT0, &env->fp_status); \
2241 DEBUG_FPU_STATE(); \ 2290 DEBUG_FPU_STATE(); \
  2291 + RETURN(); \
2242 } \ 2292 } \
2243 FLOAT_OP(name, s) \ 2293 FLOAT_OP(name, s) \
2244 { \ 2294 { \
2245 FST2 = float32_ ## name(FST0, &env->fp_status); \ 2295 FST2 = float32_ ## name(FST0, &env->fp_status); \
2246 DEBUG_FPU_STATE(); \ 2296 DEBUG_FPU_STATE(); \
  2297 + RETURN(); \
2247 } \ 2298 } \
2248 FLOAT_OP(name, ps) \ 2299 FLOAT_OP(name, ps) \
2249 { \ 2300 { \
2250 FST2 = float32_ ## name(FST0, &env->fp_status); \ 2301 FST2 = float32_ ## name(FST0, &env->fp_status); \
2251 FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \ 2302 FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
2252 DEBUG_FPU_STATE(); \ 2303 DEBUG_FPU_STATE(); \
  2304 + RETURN(); \
2253 } 2305 }
2254 FLOAT_UNOP(sqrt) 2306 FLOAT_UNOP(sqrt)
2255 #undef FLOAT_UNOP 2307 #undef FLOAT_UNOP
@@ -2260,17 +2312,20 @@ FLOAT_OP(name, d) \ @@ -2260,17 +2312,20 @@ FLOAT_OP(name, d) \
2260 { \ 2312 { \
2261 FDT2 = float64_ ## name(FDT0); \ 2313 FDT2 = float64_ ## name(FDT0); \
2262 DEBUG_FPU_STATE(); \ 2314 DEBUG_FPU_STATE(); \
  2315 + RETURN(); \
2263 } \ 2316 } \
2264 FLOAT_OP(name, s) \ 2317 FLOAT_OP(name, s) \
2265 { \ 2318 { \
2266 FST2 = float32_ ## name(FST0); \ 2319 FST2 = float32_ ## name(FST0); \
2267 DEBUG_FPU_STATE(); \ 2320 DEBUG_FPU_STATE(); \
  2321 + RETURN(); \
2268 } \ 2322 } \
2269 FLOAT_OP(name, ps) \ 2323 FLOAT_OP(name, ps) \
2270 { \ 2324 { \
2271 FST2 = float32_ ## name(FST0); \ 2325 FST2 = float32_ ## name(FST0); \
2272 FSTH2 = float32_ ## name(FSTH0); \ 2326 FSTH2 = float32_ ## name(FSTH0); \
2273 DEBUG_FPU_STATE(); \ 2327 DEBUG_FPU_STATE(); \
  2328 + RETURN(); \
2274 } 2329 }
2275 FLOAT_UNOP(abs) 2330 FLOAT_UNOP(abs)
2276 FLOAT_UNOP(chs) 2331 FLOAT_UNOP(chs)
target-mips/translate.c
@@ -402,7 +402,7 @@ enum { @@ -402,7 +402,7 @@ enum {
402 OPC_MSUB_D = 0x29 | OPC_CP3, 402 OPC_MSUB_D = 0x29 | OPC_CP3,
403 OPC_MSUB_PS = 0x2E | OPC_CP3, 403 OPC_MSUB_PS = 0x2E | OPC_CP3,
404 OPC_NMADD_S = 0x30 | OPC_CP3, 404 OPC_NMADD_S = 0x30 | OPC_CP3,
405 - OPC_NMADD_D = 0x32 | OPC_CP3, 405 + OPC_NMADD_D = 0x31 | OPC_CP3,
406 OPC_NMADD_PS= 0x36 | OPC_CP3, 406 OPC_NMADD_PS= 0x36 | OPC_CP3,
407 OPC_NMSUB_S = 0x38 | OPC_CP3, 407 OPC_NMSUB_S = 0x38 | OPC_CP3,
408 OPC_NMSUB_D = 0x39 | OPC_CP3, 408 OPC_NMSUB_D = 0x39 | OPC_CP3,
@@ -4955,6 +4955,17 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, @@ -4955,6 +4955,17 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
4955 GEN_STORE_FTN_FREG(fd, WTH2); 4955 GEN_STORE_FTN_FREG(fd, WTH2);
4956 opn = "movn.ps"; 4956 opn = "movn.ps";
4957 break; 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 case FOP(32, 22): 4969 case FOP(32, 22):
4959 CHECK_FR(ctx, fs); 4970 CHECK_FR(ctx, fs);
4960 GEN_LOAD_FREG_FTN(WTH0, fs); 4971 GEN_LOAD_FREG_FTN(WTH0, fs);
@@ -5120,47 +5131,107 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd, @@ -5120,47 +5131,107 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,
5120 opn = "madd.s"; 5131 opn = "madd.s";
5121 break; 5132 break;
5122 case OPC_MADD_D: 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 opn = "madd.d"; 5139 opn = "madd.d";
5125 break; 5140 break;
5126 case OPC_MADD_PS: 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 opn = "madd.ps"; 5151 opn = "madd.ps";
5129 break; 5152 break;
5130 case OPC_MSUB_S: 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 opn = "msub.s"; 5159 opn = "msub.s";
5133 break; 5160 break;
5134 case OPC_MSUB_D: 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 opn = "msub.d"; 5167 opn = "msub.d";
5137 break; 5168 break;
5138 case OPC_MSUB_PS: 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 opn = "msub.ps"; 5179 opn = "msub.ps";
5141 break; 5180 break;
5142 case OPC_NMADD_S: 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 opn = "nmadd.s"; 5187 opn = "nmadd.s";
5145 break; 5188 break;
5146 case OPC_NMADD_D: 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 opn = "nmadd.d"; 5195 opn = "nmadd.d";
5149 break; 5196 break;
5150 case OPC_NMADD_PS: 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 opn = "nmadd.ps"; 5207 opn = "nmadd.ps";
5153 break; 5208 break;
5154 case OPC_NMSUB_S: 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 opn = "nmsub.s"; 5215 opn = "nmsub.s";
5157 break; 5216 break;
5158 case OPC_NMSUB_D: 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 opn = "nmsub.d"; 5223 opn = "nmsub.d";
5161 break; 5224 break;
5162 case OPC_NMSUB_PS: 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 opn = "nmsub.ps"; 5235 opn = "nmsub.ps";
5165 break; 5236 break;
5166 default: 5237 default:
@@ -5562,6 +5633,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -5562,6 +5633,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
5562 gen_cp1(ctx, op1, rt, rd); 5633 gen_cp1(ctx, op1, rt, rd);
5563 break; 5634 break;
5564 case OPC_BC1: 5635 case OPC_BC1:
  5636 + case OPC_BC1ANY2:
  5637 + case OPC_BC1ANY4:
5565 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode), 5638 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5566 (rt >> 2) & 0x7, imm << 2); 5639 (rt >> 2) & 0x7, imm << 2);
5567 return; 5640 return;