| target/ppc: Fix fallback to MFSS for MFFSCRN, MFFSCRNI, MFFSCE and MFFSL |
| |
| The following commits changed the code such that these instructions became invalid |
| on pre 3.0 ISAs: |
| |
| bf8adfd88b547680aa857c46098f3a1e94373160 - target/ppc: Move mffscrn[i] to decodetree |
| 394c2e2fda70da722f20fb60412d6c0ca4bfaa03 - target/ppc: Move mffsce to decodetree |
| 3e5bce70efe6bd1f684efbb21fd2a316cbf0657e - target/ppc: Move mffsl to decodetree |
| |
| The hardware will handle them as a MFFS instruction as the code did previously. |
| Restore that behaviour. This means applications that were segfaulting under qemu |
| when encountering these instructions now operate correctly. The instruction |
| is used in glibc libm functions for example. |
| |
| Upstream-Status: Submitted [https://lore.kernel.org/qemu-devel/20230504110150.3044402-1-richard.purdie@linuxfoundation.org/] |
| |
| Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> |
| |
| Index: qemu-8.0.0/target/ppc/translate/fp-impl.c.inc |
| =================================================================== |
| --- qemu-8.0.0.orig/target/ppc/translate/fp-impl.c.inc |
| +++ qemu-8.0.0/target/ppc/translate/fp-impl.c.inc |
| @@ -584,7 +584,10 @@ static bool trans_MFFSCE(DisasContext *c |
| { |
| TCGv_i64 fpscr; |
| |
| - REQUIRE_INSNS_FLAGS2(ctx, ISA300); |
| + if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) { |
| + return trans_MFFS(ctx, a); |
| + } |
| + |
| REQUIRE_FPU(ctx); |
| |
| gen_reset_fpstatus(); |
| @@ -597,7 +600,10 @@ static bool trans_MFFSCRN(DisasContext * |
| { |
| TCGv_i64 t1, fpscr; |
| |
| - REQUIRE_INSNS_FLAGS2(ctx, ISA300); |
| + if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) { |
| + return trans_MFFS(ctx, a); |
| + } |
| + |
| REQUIRE_FPU(ctx); |
| |
| t1 = tcg_temp_new_i64(); |
| @@ -631,7 +637,10 @@ static bool trans_MFFSCRNI(DisasContext |
| { |
| TCGv_i64 t1, fpscr; |
| |
| - REQUIRE_INSNS_FLAGS2(ctx, ISA300); |
| + if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) { |
| + return trans_MFFS(ctx, a); |
| + } |
| + |
| REQUIRE_FPU(ctx); |
| |
| t1 = tcg_temp_new_i64(); |
| @@ -661,7 +670,10 @@ static bool trans_MFFSCDRNI(DisasContext |
| |
| static bool trans_MFFSL(DisasContext *ctx, arg_X_t *a) |
| { |
| - REQUIRE_INSNS_FLAGS2(ctx, ISA300); |
| + if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) { |
| + return trans_MFFS(ctx, a); |
| + } |
| + |
| REQUIRE_FPU(ctx); |
| |
| gen_reset_fpstatus(); |