Commit eb44b959de4a888d0441f05483ced589b64b4d1f
1 parent
330c483b
target-ppc: update nip before calling an helper in FP instructions
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6045 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
32 additions
and
2 deletions
target-ppc/translate.c
| @@ -2072,6 +2072,8 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \ | @@ -2072,6 +2072,8 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \ | ||
| 2072 | gen_exception(ctx, POWERPC_EXCP_FPU); \ | 2072 | gen_exception(ctx, POWERPC_EXCP_FPU); \ |
| 2073 | return; \ | 2073 | return; \ |
| 2074 | } \ | 2074 | } \ |
| 2075 | + /* NIP cannot be restored if the memory exception comes from an helper */ \ | ||
| 2076 | + gen_update_nip(ctx, ctx->nip - 4); \ | ||
| 2075 | gen_reset_fpstatus(); \ | 2077 | gen_reset_fpstatus(); \ |
| 2076 | gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \ | 2078 | gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \ |
| 2077 | cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \ | 2079 | cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \ |
| @@ -2093,6 +2095,8 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \ | @@ -2093,6 +2095,8 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \ | ||
| 2093 | gen_exception(ctx, POWERPC_EXCP_FPU); \ | 2095 | gen_exception(ctx, POWERPC_EXCP_FPU); \ |
| 2094 | return; \ | 2096 | return; \ |
| 2095 | } \ | 2097 | } \ |
| 2098 | + /* NIP cannot be restored if the memory exception comes from an helper */ \ | ||
| 2099 | + gen_update_nip(ctx, ctx->nip - 4); \ | ||
| 2096 | gen_reset_fpstatus(); \ | 2100 | gen_reset_fpstatus(); \ |
| 2097 | gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \ | 2101 | gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \ |
| 2098 | cpu_fpr[rB(ctx->opcode)]); \ | 2102 | cpu_fpr[rB(ctx->opcode)]); \ |
| @@ -2113,6 +2117,8 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \ | @@ -2113,6 +2117,8 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \ | ||
| 2113 | gen_exception(ctx, POWERPC_EXCP_FPU); \ | 2117 | gen_exception(ctx, POWERPC_EXCP_FPU); \ |
| 2114 | return; \ | 2118 | return; \ |
| 2115 | } \ | 2119 | } \ |
| 2120 | + /* NIP cannot be restored if the memory exception comes from an helper */ \ | ||
| 2121 | + gen_update_nip(ctx, ctx->nip - 4); \ | ||
| 2116 | gen_reset_fpstatus(); \ | 2122 | gen_reset_fpstatus(); \ |
| 2117 | gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \ | 2123 | gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \ |
| 2118 | cpu_fpr[rC(ctx->opcode)]); \ | 2124 | cpu_fpr[rC(ctx->opcode)]); \ |
| @@ -2133,6 +2139,8 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \ | @@ -2133,6 +2139,8 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \ | ||
| 2133 | gen_exception(ctx, POWERPC_EXCP_FPU); \ | 2139 | gen_exception(ctx, POWERPC_EXCP_FPU); \ |
| 2134 | return; \ | 2140 | return; \ |
| 2135 | } \ | 2141 | } \ |
| 2142 | + /* NIP cannot be restored if the memory exception comes from an helper */ \ | ||
| 2143 | + gen_update_nip(ctx, ctx->nip - 4); \ | ||
| 2136 | gen_reset_fpstatus(); \ | 2144 | gen_reset_fpstatus(); \ |
| 2137 | gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \ | 2145 | gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \ |
| 2138 | gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \ | 2146 | gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \ |
| @@ -2146,6 +2154,8 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \ | @@ -2146,6 +2154,8 @@ GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \ | ||
| 2146 | gen_exception(ctx, POWERPC_EXCP_FPU); \ | 2154 | gen_exception(ctx, POWERPC_EXCP_FPU); \ |
| 2147 | return; \ | 2155 | return; \ |
| 2148 | } \ | 2156 | } \ |
| 2157 | + /* NIP cannot be restored if the memory exception comes from an helper */ \ | ||
| 2158 | + gen_update_nip(ctx, ctx->nip - 4); \ | ||
| 2149 | gen_reset_fpstatus(); \ | 2159 | gen_reset_fpstatus(); \ |
| 2150 | gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \ | 2160 | gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \ |
| 2151 | gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \ | 2161 | gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \ |
| @@ -2175,6 +2185,8 @@ GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES) | @@ -2175,6 +2185,8 @@ GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES) | ||
| 2175 | gen_exception(ctx, POWERPC_EXCP_FPU); | 2185 | gen_exception(ctx, POWERPC_EXCP_FPU); |
| 2176 | return; | 2186 | return; |
| 2177 | } | 2187 | } |
| 2188 | + /* NIP cannot be restored if the memory exception comes from an helper */ | ||
| 2189 | + gen_update_nip(ctx, ctx->nip - 4); | ||
| 2178 | gen_reset_fpstatus(); | 2190 | gen_reset_fpstatus(); |
| 2179 | gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); | 2191 | gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); |
| 2180 | gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); | 2192 | gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); |
| @@ -2193,6 +2205,8 @@ GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) | @@ -2193,6 +2205,8 @@ GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) | ||
| 2193 | gen_exception(ctx, POWERPC_EXCP_FPU); | 2205 | gen_exception(ctx, POWERPC_EXCP_FPU); |
| 2194 | return; | 2206 | return; |
| 2195 | } | 2207 | } |
| 2208 | + /* NIP cannot be restored if the memory exception comes from an helper */ | ||
| 2209 | + gen_update_nip(ctx, ctx->nip - 4); | ||
| 2196 | gen_reset_fpstatus(); | 2210 | gen_reset_fpstatus(); |
| 2197 | gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); | 2211 | gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); |
| 2198 | gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0); | 2212 | gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0); |
| @@ -2204,6 +2218,8 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) | @@ -2204,6 +2218,8 @@ GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT) | ||
| 2204 | gen_exception(ctx, POWERPC_EXCP_FPU); | 2218 | gen_exception(ctx, POWERPC_EXCP_FPU); |
| 2205 | return; | 2219 | return; |
| 2206 | } | 2220 | } |
| 2221 | + /* NIP cannot be restored if the memory exception comes from an helper */ | ||
| 2222 | + gen_update_nip(ctx, ctx->nip - 4); | ||
| 2207 | gen_reset_fpstatus(); | 2223 | gen_reset_fpstatus(); |
| 2208 | gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); | 2224 | gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); |
| 2209 | gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); | 2225 | gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); |
| @@ -2254,6 +2270,8 @@ GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) | @@ -2254,6 +2270,8 @@ GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) | ||
| 2254 | gen_exception(ctx, POWERPC_EXCP_FPU); | 2270 | gen_exception(ctx, POWERPC_EXCP_FPU); |
| 2255 | return; | 2271 | return; |
| 2256 | } | 2272 | } |
| 2273 | + /* NIP cannot be restored if the memory exception comes from an helper */ | ||
| 2274 | + gen_update_nip(ctx, ctx->nip - 4); | ||
| 2257 | gen_reset_fpstatus(); | 2275 | gen_reset_fpstatus(); |
| 2258 | crf = tcg_const_i32(crfD(ctx->opcode)); | 2276 | crf = tcg_const_i32(crfD(ctx->opcode)); |
| 2259 | gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf); | 2277 | gen_helper_fcmpo(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf); |
| @@ -2269,6 +2287,8 @@ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) | @@ -2269,6 +2287,8 @@ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) | ||
| 2269 | gen_exception(ctx, POWERPC_EXCP_FPU); | 2287 | gen_exception(ctx, POWERPC_EXCP_FPU); |
| 2270 | return; | 2288 | return; |
| 2271 | } | 2289 | } |
| 2290 | + /* NIP cannot be restored if the memory exception comes from an helper */ | ||
| 2291 | + gen_update_nip(ctx, ctx->nip - 4); | ||
| 2272 | gen_reset_fpstatus(); | 2292 | gen_reset_fpstatus(); |
| 2273 | crf = tcg_const_i32(crfD(ctx->opcode)); | 2293 | crf = tcg_const_i32(crfD(ctx->opcode)); |
| 2274 | gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf); | 2294 | gen_helper_fcmpu(cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)], crf); |
| @@ -2340,7 +2360,10 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT) | @@ -2340,7 +2360,10 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT) | ||
| 2340 | crb = 31 - crbD(ctx->opcode); | 2360 | crb = 31 - crbD(ctx->opcode); |
| 2341 | gen_reset_fpstatus(); | 2361 | gen_reset_fpstatus(); |
| 2342 | if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) { | 2362 | if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) { |
| 2343 | - TCGv_i32 t0 = tcg_const_i32(crb); | 2363 | + TCGv_i32 t0; |
| 2364 | + /* NIP cannot be restored if the memory exception comes from an helper */ | ||
| 2365 | + gen_update_nip(ctx, ctx->nip - 4); | ||
| 2366 | + t0 = tcg_const_i32(crb); | ||
| 2344 | gen_helper_fpscr_clrbit(t0); | 2367 | gen_helper_fpscr_clrbit(t0); |
| 2345 | tcg_temp_free_i32(t0); | 2368 | tcg_temp_free_i32(t0); |
| 2346 | } | 2369 | } |
| @@ -2362,7 +2385,10 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT) | @@ -2362,7 +2385,10 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT) | ||
| 2362 | gen_reset_fpstatus(); | 2385 | gen_reset_fpstatus(); |
| 2363 | /* XXX: we pretend we can only do IEEE floating-point computations */ | 2386 | /* XXX: we pretend we can only do IEEE floating-point computations */ |
| 2364 | if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) { | 2387 | if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) { |
| 2365 | - TCGv_i32 t0 = tcg_const_i32(crb); | 2388 | + TCGv_i32 t0; |
| 2389 | + /* NIP cannot be restored if the memory exception comes from an helper */ | ||
| 2390 | + gen_update_nip(ctx, ctx->nip - 4); | ||
| 2391 | + t0 = tcg_const_i32(crb); | ||
| 2366 | gen_helper_fpscr_setbit(t0); | 2392 | gen_helper_fpscr_setbit(t0); |
| 2367 | tcg_temp_free_i32(t0); | 2393 | tcg_temp_free_i32(t0); |
| 2368 | } | 2394 | } |
| @@ -2382,6 +2408,8 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) | @@ -2382,6 +2408,8 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) | ||
| 2382 | gen_exception(ctx, POWERPC_EXCP_FPU); | 2408 | gen_exception(ctx, POWERPC_EXCP_FPU); |
| 2383 | return; | 2409 | return; |
| 2384 | } | 2410 | } |
| 2411 | + /* NIP cannot be restored if the memory exception comes from an helper */ | ||
| 2412 | + gen_update_nip(ctx, ctx->nip - 4); | ||
| 2385 | gen_reset_fpstatus(); | 2413 | gen_reset_fpstatus(); |
| 2386 | t0 = tcg_const_i32(FM(ctx->opcode)); | 2414 | t0 = tcg_const_i32(FM(ctx->opcode)); |
| 2387 | gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0); | 2415 | gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0); |
| @@ -2406,6 +2434,8 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) | @@ -2406,6 +2434,8 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) | ||
| 2406 | } | 2434 | } |
| 2407 | bf = crbD(ctx->opcode) >> 2; | 2435 | bf = crbD(ctx->opcode) >> 2; |
| 2408 | sh = 7 - bf; | 2436 | sh = 7 - bf; |
| 2437 | + /* NIP cannot be restored if the memory exception comes from an helper */ | ||
| 2438 | + gen_update_nip(ctx, ctx->nip - 4); | ||
| 2409 | gen_reset_fpstatus(); | 2439 | gen_reset_fpstatus(); |
| 2410 | t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh)); | 2440 | t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh)); |
| 2411 | t1 = tcg_const_i32(1 << sh); | 2441 | t1 = tcg_const_i32(1 << sh); |