Re: [PATCH 16/33] target/ppc: Implement Vector Insert Word from GPR using Immediate insns

2021-10-26 Thread Paul A. Clarke
On Tue, Oct 26, 2021 at 09:58:15AM -0700, Richard Henderson wrote:
> On 10/26/21 7:33 AM, Matheus K. Ferst wrote:
> > It says that "if UIM is greater than N, the result is undefined." My
> > first read was also that the outcome is "boundedly undefined," but I
> > guess it can be understood as "the resulting value in VRT will be
> > undefined" (like when the pseudo-code uses "VRT <- 0x_..._"), in
> > which case this patch and Mambo are correct.
> 
> If the reference simulator is fine with it, I am too.

FYI, it appears that the hardware does a partial insert, per an experiment:
```
1: x/i $pc
=> 0x16d4 :  vinsw   v2,r3,14
(gdb) p $v2.v4_int32
$1 = {0x1, 0x1, 0x1, 0x1}
(gdb) p $r3
$2 = 0x12345678
(gdb) nexti
(gdb) p $v2.v4_int32
$3 = {0x1234, 0x1, 0x1, 0x1}


> I'm just a bit disappointed with the laxness of the pseudocode -- they've
> got that 0x syntax elsewhere, but not here.

PC



RE: [PATCH v2 02/16] target/ppc: add user read functions for MMCR0 and MMCR2

2021-08-25 Thread Paul A. Clarke
On Wed, Aug 25, 2021 at 02:30:11PM +1000, David Gibson wrote:
> On Tue, Aug 24, 2021 at 01:30:18PM -0300, Daniel Henrique Barboza wrote:
> > From: Gustavo Romero 
> > 
> > This patch adds handling of UMMCR0 and UMMCR2 user read which,
> > according to PowerISA 3.1, has some bits ommited to the
> 
> Nit: One 'm' in "omited".

Let's trade that extra 'm' for a 't', FTW:  "omitted".  :-)

PC



Re: [PATCH v2] target/ppc: Fix load endianness for lxvwsx/lxvdsx

2021-05-18 Thread Paul A. Clarke
Thanks, all!  My original patch which addressed this issue
for me probably should've been labeled as an RFC.  Thanks for your
willingness to review it, in spite of its problems.  It was a bit
of a stab in the dark. I hope it at least helped get to this solution.

Tested-by: Paul A. Clarke 

Do I need to do anything about the GitLab issue?
https://gitlab.com/qemu-project/qemu/-/issues/212

(I couldn't even figure out how to subscribe to my own issue,
or if I already was, or who might have been notified of its
existence, or if discussion should happen there or here.)

On Tue, May 18, 2021 at 03:30:20PM +0200, Giuseppe Musacchio wrote:
> TARGET_WORDS_BIGENDIAN may not match the machine endianness if that's a
> runtime-configurable parameter.
> 
> Fixes: bcb0b7b1a1c05707304f80ca6f523d557816f85c
> Fixes: afae37d98ae991c0792c867dbd9f32f988044318
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/212
> 
> Signed-off-by: Giuseppe Musacchio 
> ---
>  target/ppc/translate/vsx-impl.c.inc | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/target/ppc/translate/vsx-impl.c.inc 
> b/target/ppc/translate/vsx-impl.c.inc
> index b817d31260..57a7f73bba 100644
> --- a/target/ppc/translate/vsx-impl.c.inc
> +++ b/target/ppc/translate/vsx-impl.c.inc
> @@ -139,7 +139,7 @@ static void gen_lxvwsx(DisasContext *ctx)
>  gen_addr_reg_index(ctx, EA);
>  
>  data = tcg_temp_new_i32();
> -tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, MO_TEUL);
> +tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UL));
>  tcg_gen_gvec_dup_i32(MO_UL, vsr_full_offset(xT(ctx->opcode)), 16, 16, 
> data);
>  
>  tcg_temp_free(EA);
> @@ -162,7 +162,7 @@ static void gen_lxvdsx(DisasContext *ctx)
>  gen_addr_reg_index(ctx, EA);
>  
>  data = tcg_temp_new_i64();
> -tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, MO_TEQ);
> +tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_Q));
>  tcg_gen_gvec_dup_i64(MO_Q, vsr_full_offset(xT(ctx->opcode)), 16, 16, 
> data);
>  
>  tcg_temp_free(EA);
> -- 
> 2.30.2

PC



[PATCH] Fix `lxvdsx` (issue #212)

2021-05-17 Thread Paul A. Clarke
`lxvdsx` is byte-swapping the data it loads, which it should not
do.  Fix it.

Fixes #212.

Fixes: bcb0b7b1a1c05707304f80ca6f523d557816f85c
Signed-off-by:  Paul A. Clarke mem_idx, MO_TEQ);
+tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, MO_LEQ);
 tcg_gen_gvec_dup_i64(MO_Q, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
 
 tcg_temp_free(EA);
-- 
2.27.0




[Qemu-devel] [PATCH] ppc: Use FPSCR defines instead of constants

2019-09-18 Thread Paul A. Clarke
From: "Paul A. Clarke" 

There are FPSCR-related defines in target/ppc/cpu.h which can be used in
place of constants and explicit shifts which arguably improve the code a
bit in places.

Signed-off-by: Paul A. Clarke 
---
I confirmed that the generated assembly is identical before and after
the patch.

 target/ppc/dfp_helper.c |   8 ++--
 target/ppc/fpu_helper.c | 122 
 2 files changed, 65 insertions(+), 65 deletions(-)

diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c
index da8e08a..7533991 100644
--- a/target/ppc/dfp_helper.c
+++ b/target/ppc/dfp_helper.c
@@ -220,8 +220,8 @@ static void dfp_set_FPRF_from_FRT_with_context(struct 
PPC_DFP *dfp,
 default:
 assert(0); /* should never get here */
 }
-dfp->env->fpscr &= ~(0x1F << 12);
-dfp->env->fpscr |= (fprf << 12);
+dfp->env->fpscr &= ~FP_FPRF;
+dfp->env->fpscr |= (fprf << FPSCR_FPRF);
 }
 
 static void dfp_set_FPRF_from_FRT(struct PPC_DFP *dfp)
@@ -369,8 +369,8 @@ static void dfp_set_CRBF_from_T(struct PPC_DFP *dfp)
 
 static void dfp_set_FPCC_from_CRBF(struct PPC_DFP *dfp)
 {
-dfp->env->fpscr &= ~(0xF << 12);
-dfp->env->fpscr |= (dfp->crbf << 12);
+dfp->env->fpscr &= ~FP_FPCC;
+dfp->env->fpscr |= (dfp->crbf << FPSCR_FPCC);
 }
 
 static inline void dfp_makeQNaN(decNumber *dn)
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 4b1a2e6..dc38324 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -180,7 +180,7 @@ static void set_fprf_from_class(CPUPPCState *env, int class)
 };
 bool isneg = class & is_neg;
 
-env->fpscr &= ~(0x1F << FPSCR_FPRF);
+env->fpscr &= ~FP_FPRF;
 env->fpscr |= fprf[ctz32(class)][isneg] << FPSCR_FPRF;
 }
 
@@ -199,12 +199,12 @@ COMPUTE_FPRF(float128)
 static void finish_invalid_op_excp(CPUPPCState *env, int op, uintptr_t retaddr)
 {
 /* Update the floating-point invalid operation summary */
-env->fpscr |= 1 << FPSCR_VX;
+env->fpscr |= FP_VX;
 /* Update the floating-point exception summary */
 env->fpscr |= FP_FX;
 if (fpscr_ve != 0) {
 /* Update the floating-point enabled exception summary */
-env->fpscr |= 1 << FPSCR_FEX;
+env->fpscr |= FP_FEX;
 if (fp_exceptions_enabled(env)) {
 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_FP | op, retaddr);
@@ -215,11 +215,11 @@ static void finish_invalid_op_excp(CPUPPCState *env, int 
op, uintptr_t retaddr)
 static void finish_invalid_op_arith(CPUPPCState *env, int op,
 bool set_fpcc, uintptr_t retaddr)
 {
-env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
+env->fpscr &= ~(FP_FR | FP_FI);
 if (fpscr_ve == 0) {
 if (set_fpcc) {
-env->fpscr &= ~(0xF << FPSCR_FPCC);
-env->fpscr |= 0x11 << FPSCR_FPCC;
+env->fpscr &= ~FP_FPCC;
+env->fpscr |= (FP_C | FP_FU);
 }
 }
 finish_invalid_op_excp(env, op, retaddr);
@@ -228,7 +228,7 @@ static void finish_invalid_op_arith(CPUPPCState *env, int 
op,
 /* Signalling NaN */
 static void float_invalid_op_vxsnan(CPUPPCState *env, uintptr_t retaddr)
 {
-env->fpscr |= 1 << FPSCR_VXSNAN;
+env->fpscr |= FP_VXSNAN;
 finish_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, retaddr);
 }
 
@@ -236,7 +236,7 @@ static void float_invalid_op_vxsnan(CPUPPCState *env, 
uintptr_t retaddr)
 static void float_invalid_op_vxisi(CPUPPCState *env, bool set_fpcc,
uintptr_t retaddr)
 {
-env->fpscr |= 1 << FPSCR_VXISI;
+env->fpscr |= FP_VXISI;
 finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXISI, set_fpcc, retaddr);
 }
 
@@ -244,7 +244,7 @@ static void float_invalid_op_vxisi(CPUPPCState *env, bool 
set_fpcc,
 static void float_invalid_op_vxidi(CPUPPCState *env, bool set_fpcc,
uintptr_t retaddr)
 {
-env->fpscr |= 1 << FPSCR_VXIDI;
+env->fpscr |= FP_VXIDI;
 finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXIDI, set_fpcc, retaddr);
 }
 
@@ -252,7 +252,7 @@ static void float_invalid_op_vxidi(CPUPPCState *env, bool 
set_fpcc,
 static void float_invalid_op_vxzdz(CPUPPCState *env, bool set_fpcc,
uintptr_t retaddr)
 {
-env->fpscr |= 1 << FPSCR_VXZDZ;
+env->fpscr |= FP_VXZDZ;
 finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXZDZ, set_fpcc, retaddr);
 }
 
@@ -260,7 +260,7 @@ static void float_invalid_op_vxzdz(CPUPPCState *env, bool 
set_fpcc,
 static void float_invalid_op_vximz(CPUPPCState *env, bool set_fpcc,
uintptr_t retaddr)
 {
-env->f

[Qemu-devel] [PATCH v3 1/2] ppc: Add support for 'mffscrn', 'mffscrni' instructions

2019-09-18 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffscrn' and 'mffscrni' instructions.

'mffscrn' and 'mffscrni' are similar to 'mffsl', except they do not return
the status bits (FI, FR, FPRF) and they also set the rounding mode in the
FPSCR.

On CPUs without support for 'mffscrn'/'mffscrni' (below ISA 3.0), the
instructions will execute identically to 'mffs'.

Signed-off-by: Paul A. Clarke 
---
v3:
- Fix v2 change which cleared inadvertently clearned DRN.
- Remove FP_MODE, use FP_DRN and FP_RN explicitly instead.
- I did not remove the FPSCR_DRN[012] or FP_DRN[012] defines, as it's
  clearer to me that it's a 3-bit field, but am happy to respin if that
  is preferred.
v2:
- Add DRN to returned FPSCR value.
- Add DRN defines to target/ppc/cpu.h.

 target/ppc/cpu.h   |  9 -
 target/ppc/dfp_helper.c|  2 +-
 target/ppc/internal.h  |  3 ++
 target/ppc/translate/fp-impl.inc.c | 69 +-
 target/ppc/translate/fp-ops.inc.c  |  4 +++
 5 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index eaee1a5..a23c645 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -559,6 +559,9 @@ enum {
 
 /*/
 /* Floating point status and control register*/
+#define FPSCR_DRN2   34 /* Decimal Floating-Point rounding control   */
+#define FPSCR_DRN1   33 /* Decimal Floating-Point rounding control   */
+#define FPSCR_DRN0   32 /* Decimal Floating-Point rounding control   */
 #define FPSCR_FX 31 /* Floating-point exception summary  */
 #define FPSCR_FEX30 /* Floating-point enabled exception summary  */
 #define FPSCR_VX 29 /* Floating-point invalid operation exception summ.  */
@@ -592,6 +595,7 @@ enum {
 #define FPSCR_NI 2  /* Floating-point non-IEEE mode  */
 #define FPSCR_RN11
 #define FPSCR_RN00  /* Floating-point rounding control   */
+#define fpscr_drn(((env->fpscr) & FP_DRN) >> FPSCR_DRN0)
 #define fpscr_fex(((env->fpscr) >> FPSCR_FEX)& 0x1)
 #define fpscr_vx (((env->fpscr) >> FPSCR_VX) & 0x1)
 #define fpscr_ox (((env->fpscr) >> FPSCR_OX) & 0x1)
@@ -627,6 +631,10 @@ enum {
 #define fpscr_eex (((env->fpscr) >> FPSCR_XX) & ((env->fpscr) >> FPSCR_XE) &  \
0x1F)
 
+#define FP_DRN2 (1ull << FPSCR_DRN2)
+#define FP_DRN1 (1ull << FPSCR_DRN1)
+#define FP_DRN0 (1ull << FPSCR_DRN0)
+#define FP_DRN  (FP_DRN2 | FP_DRN1 | FP_DRN0)
 #define FP_FX   (1ull << FPSCR_FX)
 #define FP_FEX  (1ull << FPSCR_FEX)
 #define FP_VX   (1ull << FPSCR_VX)
@@ -662,7 +670,6 @@ enum {
 #define FP_RN0  (1ull << FPSCR_RN0)
 #define FP_RN   (FP_RN1 | FP_RN0)
 
-#define FP_MODE FP_RN
 #define FP_ENABLES  (FP_VE | FP_OE | FP_UE | FP_ZE | FP_XE)
 #define FP_STATUS   (FP_FR | FP_FI | FP_FPRF)
 
diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c
index f102177..da8e08a 100644
--- a/target/ppc/dfp_helper.c
+++ b/target/ppc/dfp_helper.c
@@ -48,7 +48,7 @@ static void dfp_prepare_rounding_mode(decContext *context, 
uint64_t fpscr)
 {
 enum rounding rnd;
 
-switch ((fpscr >> 32) & 0x7) {
+switch ((fpscr & FP_DRN) >> FPSCR_DRN0) {
 case 0:
 rnd = DEC_ROUND_HALF_EVEN;
 break;
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index d3d327e..15d655b 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -157,6 +157,9 @@ EXTRACT_HELPER(FPL, 25, 1);
 EXTRACT_HELPER(FPFLM, 17, 8);
 EXTRACT_HELPER(FPW, 16, 1);
 
+/* mffscrni */
+EXTRACT_HELPER(RM, 11, 2);
+
 /* addpcis */
 EXTRACT_HELPER_SPLIT_3(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0)
 #if defined(TARGET_PPC64)
diff --git a/target/ppc/translate/fp-impl.inc.c 
b/target/ppc/translate/fp-impl.inc.c
index 7cd9d8d..75f9523 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -634,11 +634,78 @@ static void gen_mffsl(DisasContext *ctx)
 gen_reset_fpstatus();
 tcg_gen_extu_tl_i64(t0, cpu_fpscr);
 /* Mask everything except mode, status, and enables.  */
-tcg_gen_andi_i64(t0, t0, FP_MODE | FP_STATUS | FP_ENABLES);
+tcg_gen_andi_i64(t0, t0, FP_DRN | FP_STATUS | FP_ENABLES | FP_RN);
 set_fpr(rD(ctx->opcode), t0);
 tcg_temp_free_i64(t0);
 }
 
+static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
+{
+TCGv_i64 t0 = tcg_temp_new_i64();
+TCGv_i32 mask = tcg_const_i32(0x0001);
+
+gen_reset_fpstatus();
+tcg_gen_extu_tl_

[Qemu-devel] [PATCH v3 2/2] ppc: Add support for 'mffsce' instruction

2019-09-18 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffsce' instruction.

'mffsce' is identical to 'mffs', except that it also clears the exception
enable bits in the FPSCR.

On CPUs without support for 'mffsce' (below ISA 3.0), the
instruction will execute identically to 'mffs'.

Signed-off-by: Paul A. Clarke 
Reviewed-by: Richard Henderson 
---
v3: no changes.
v2: no changes.

 target/ppc/translate/fp-impl.inc.c | 30 ++
 target/ppc/translate/fp-ops.inc.c  |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/target/ppc/translate/fp-impl.inc.c 
b/target/ppc/translate/fp-impl.inc.c
index 75f9523..d8e27bf 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -639,6 +639,36 @@ static void gen_mffsl(DisasContext *ctx)
 tcg_temp_free_i64(t0);
 }
 
+/* mffsce */
+static void gen_mffsce(DisasContext *ctx)
+{
+TCGv_i64 t0;
+TCGv_i32 mask;
+
+if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
+return gen_mffs(ctx);
+}
+
+if (unlikely(!ctx->fpu_enabled)) {
+gen_exception(ctx, POWERPC_EXCP_FPU);
+return;
+}
+
+t0 = tcg_temp_new_i64();
+
+gen_reset_fpstatus();
+tcg_gen_extu_tl_i64(t0, cpu_fpscr);
+set_fpr(rD(ctx->opcode), t0);
+
+/* Clear exception enable bits in the FPSCR.  */
+tcg_gen_andi_i64(t0, t0, ~FP_ENABLES);
+mask = tcg_const_i32(0x0003);
+gen_helper_store_fpscr(cpu_env, t0, mask);
+
+tcg_temp_free_i32(mask);
+tcg_temp_free_i64(t0);
+}
+
 static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
 {
 TCGv_i64 t0 = tcg_temp_new_i64();
diff --git a/target/ppc/translate/fp-ops.inc.c 
b/target/ppc/translate/fp-ops.inc.c
index f2bcf0e..88fab65 100644
--- a/target/ppc/translate/fp-ops.inc.c
+++ b/target/ppc/translate/fp-ops.inc.c
@@ -105,6 +105,8 @@ GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x0001, 
PPC_NONE, PPC2_VSX207),
 GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x0001, PPC_NONE, PPC2_VSX207),
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
 GEN_HANDLER_E_2(mffs, 0x3F, 0x07, 0x12, 0x00, 0x, PPC_FLOAT, PPC_NONE),
+GEN_HANDLER_E_2(mffsce, 0x3F, 0x07, 0x12, 0x01, 0x, PPC_FLOAT,
+PPC2_ISA300),
 GEN_HANDLER_E_2(mffsl, 0x3F, 0x07, 0x12, 0x18, 0x, PPC_FLOAT,
 PPC2_ISA300),
 GEN_HANDLER_E_2(mffscrn, 0x3F, 0x07, 0x12, 0x16, 0x, PPC_FLOAT,
-- 
1.8.3.1




[Qemu-devel] [PATCH v2 1/2] ppc: Add support for 'mffscrn', 'mffscrni' instructions

2019-09-16 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffscrn' and 'mffscrni' instructions.

'mffscrn' and 'mffscrni' are similar to 'mffsl', except they do not return
the status bits (FI, FR, FPRF) and they also set the rounding mode in the
FPSCR.

On CPUs without support for 'mffscrn'/'mffscrni' (below ISA 3.0), the
instructions will execute identically to 'mffs'.

Signed-off-by: Paul A. Clarke 
---
v2:
- Add DRN to returned FPSCR value.
- Add DRN defines to target/ppc/cpu.h.

 target/ppc/cpu.h   | 10 +-
 target/ppc/dfp_helper.c|  2 +-
 target/ppc/internal.h  |  3 ++
 target/ppc/translate/fp-impl.inc.c | 67 ++
 target/ppc/translate/fp-ops.inc.c  |  4 +++
 5 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index eaee1a5..dcea2f0 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -559,6 +559,9 @@ enum {
 
 /*/
 /* Floating point status and control register*/
+#define FPSCR_DRN2   34 /* Decimal Floating-Point rounding control   */
+#define FPSCR_DRN1   33 /* Decimal Floating-Point rounding control   */
+#define FPSCR_DRN0   32 /* Decimal Floating-Point rounding control   */
 #define FPSCR_FX 31 /* Floating-point exception summary  */
 #define FPSCR_FEX30 /* Floating-point enabled exception summary  */
 #define FPSCR_VX 29 /* Floating-point invalid operation exception summ.  */
@@ -592,6 +595,7 @@ enum {
 #define FPSCR_NI 2  /* Floating-point non-IEEE mode  */
 #define FPSCR_RN11
 #define FPSCR_RN00  /* Floating-point rounding control   */
+#define fpscr_drn(((env->fpscr) & FP_DRN) >> FPSCR_DRN0)
 #define fpscr_fex(((env->fpscr) >> FPSCR_FEX)& 0x1)
 #define fpscr_vx (((env->fpscr) >> FPSCR_VX) & 0x1)
 #define fpscr_ox (((env->fpscr) >> FPSCR_OX) & 0x1)
@@ -627,6 +631,10 @@ enum {
 #define fpscr_eex (((env->fpscr) >> FPSCR_XX) & ((env->fpscr) >> FPSCR_XE) &  \
0x1F)
 
+#define FP_DRN2 (1ull << FPSCR_DRN2)
+#define FP_DRN1 (1ull << FPSCR_DRN1)
+#define FP_DRN0 (1ull << FPSCR_DRN0)
+#define FP_DRN  (FP_DRN2 | FP_DRN1 | FP_DRN0)
 #define FP_FX   (1ull << FPSCR_FX)
 #define FP_FEX  (1ull << FPSCR_FEX)
 #define FP_VX   (1ull << FPSCR_VX)
@@ -662,7 +670,7 @@ enum {
 #define FP_RN0  (1ull << FPSCR_RN0)
 #define FP_RN   (FP_RN1 | FP_RN0)
 
-#define FP_MODE FP_RN
+#define FP_MODE (FP_DRN | FP_RN)
 #define FP_ENABLES  (FP_VE | FP_OE | FP_UE | FP_ZE | FP_XE)
 #define FP_STATUS   (FP_FR | FP_FI | FP_FPRF)
 
diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c
index f102177..da8e08a 100644
--- a/target/ppc/dfp_helper.c
+++ b/target/ppc/dfp_helper.c
@@ -48,7 +48,7 @@ static void dfp_prepare_rounding_mode(decContext *context, 
uint64_t fpscr)
 {
 enum rounding rnd;
 
-switch ((fpscr >> 32) & 0x7) {
+switch ((fpscr & FP_DRN) >> FPSCR_DRN0) {
 case 0:
 rnd = DEC_ROUND_HALF_EVEN;
 break;
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index d3d327e..15d655b 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -157,6 +157,9 @@ EXTRACT_HELPER(FPL, 25, 1);
 EXTRACT_HELPER(FPFLM, 17, 8);
 EXTRACT_HELPER(FPW, 16, 1);
 
+/* mffscrni */
+EXTRACT_HELPER(RM, 11, 2);
+
 /* addpcis */
 EXTRACT_HELPER_SPLIT_3(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0)
 #if defined(TARGET_PPC64)
diff --git a/target/ppc/translate/fp-impl.inc.c 
b/target/ppc/translate/fp-impl.inc.c
index 7cd9d8d..59a4faf 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -639,6 +639,73 @@ static void gen_mffsl(DisasContext *ctx)
 tcg_temp_free_i64(t0);
 }
 
+static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
+{
+TCGv_i64 t0 = tcg_temp_new_i64();
+TCGv_i32 mask = tcg_const_i32(0x0001);
+
+gen_reset_fpstatus();
+tcg_gen_extu_tl_i64(t0, cpu_fpscr);
+tcg_gen_andi_i64(t0, t0, FP_MODE | FP_ENABLES);
+set_fpr(rD(ctx->opcode), t0);
+
+/* Mask FPSCR value to clear RN.  */
+tcg_gen_andi_i64(t0, t0, ~FP_MODE);
+
+/* Merge RN into FPSCR value.  */
+tcg_gen_or_i64(t0, t0, t1);
+
+gen_helper_store_fpscr(cpu_env, t0, mask);
+
+tcg_temp_free_i32(mask);
+tcg_temp_free_i64(t0);
+}
+
+/* mffscrn */
+static void gen_mffscrn(DisasContext *ctx)
+{
+TCGv_i64 t1;
+
+if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
+return gen

[Qemu-devel] [PATCH v2 2/2] ppc: Add support for 'mffsce' instruction

2019-09-16 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffsce' instruction.

'mffsce' is identical to 'mffs', except that it also clears the exception
enable bits in the FPSCR.

On CPUs without support for 'mffsce' (below ISA 3.0), the
instruction will execute identically to 'mffs'.

Signed-off-by: Paul A. Clarke 
---
v2: no changes.

 target/ppc/translate/fp-impl.inc.c | 30 ++
 target/ppc/translate/fp-ops.inc.c  |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/target/ppc/translate/fp-impl.inc.c 
b/target/ppc/translate/fp-impl.inc.c
index 59a4faf..34edc45 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -639,6 +639,36 @@ static void gen_mffsl(DisasContext *ctx)
 tcg_temp_free_i64(t0);
 }
 
+/* mffsce */
+static void gen_mffsce(DisasContext *ctx)
+{
+TCGv_i64 t0;
+TCGv_i32 mask;
+
+if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
+return gen_mffs(ctx);
+}
+
+if (unlikely(!ctx->fpu_enabled)) {
+gen_exception(ctx, POWERPC_EXCP_FPU);
+return;
+}
+
+t0 = tcg_temp_new_i64();
+
+gen_reset_fpstatus();
+tcg_gen_extu_tl_i64(t0, cpu_fpscr);
+set_fpr(rD(ctx->opcode), t0);
+
+/* Clear exception enable bits in the FPSCR.  */
+tcg_gen_andi_i64(t0, t0, ~FP_ENABLES);
+mask = tcg_const_i32(0x0003);
+gen_helper_store_fpscr(cpu_env, t0, mask);
+
+tcg_temp_free_i32(mask);
+tcg_temp_free_i64(t0);
+}
+
 static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
 {
 TCGv_i64 t0 = tcg_temp_new_i64();
diff --git a/target/ppc/translate/fp-ops.inc.c 
b/target/ppc/translate/fp-ops.inc.c
index f2bcf0e..88fab65 100644
--- a/target/ppc/translate/fp-ops.inc.c
+++ b/target/ppc/translate/fp-ops.inc.c
@@ -105,6 +105,8 @@ GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x0001, 
PPC_NONE, PPC2_VSX207),
 GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x0001, PPC_NONE, PPC2_VSX207),
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
 GEN_HANDLER_E_2(mffs, 0x3F, 0x07, 0x12, 0x00, 0x, PPC_FLOAT, PPC_NONE),
+GEN_HANDLER_E_2(mffsce, 0x3F, 0x07, 0x12, 0x01, 0x, PPC_FLOAT,
+PPC2_ISA300),
 GEN_HANDLER_E_2(mffsl, 0x3F, 0x07, 0x12, 0x18, 0x, PPC_FLOAT,
 PPC2_ISA300),
 GEN_HANDLER_E_2(mffscrn, 0x3F, 0x07, 0x12, 0x16, 0x, PPC_FLOAT,
-- 
1.8.3.1




[Qemu-devel] [PATCH] ppc: Add support for 'mffsce' instruction

2019-09-12 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffsce' instruction.

'mffsce' is identical to 'mffs', except that it also clears the exception
enable bits in the FPSCR.

On CPUs without support for 'mffsce' (below ISA 3.0), the
instruction will execute identically to 'mffs'.

Signed-off-by: Paul A. Clarke 
---
 target/ppc/translate/fp-impl.inc.c | 30 ++
 target/ppc/translate/fp-ops.inc.c  |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/target/ppc/translate/fp-impl.inc.c 
b/target/ppc/translate/fp-impl.inc.c
index 59a4faf..34edc45 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -639,6 +639,36 @@ static void gen_mffsl(DisasContext *ctx)
 tcg_temp_free_i64(t0);
 }
 
+/* mffsce */
+static void gen_mffsce(DisasContext *ctx)
+{
+TCGv_i64 t0;
+TCGv_i32 mask;
+
+if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
+return gen_mffs(ctx);
+}
+
+if (unlikely(!ctx->fpu_enabled)) {
+gen_exception(ctx, POWERPC_EXCP_FPU);
+return;
+}
+
+t0 = tcg_temp_new_i64();
+
+gen_reset_fpstatus();
+tcg_gen_extu_tl_i64(t0, cpu_fpscr);
+set_fpr(rD(ctx->opcode), t0);
+
+/* Clear exception enable bits in the FPSCR.  */
+tcg_gen_andi_i64(t0, t0, ~FP_ENABLES);
+mask = tcg_const_i32(0x0003);
+gen_helper_store_fpscr(cpu_env, t0, mask);
+
+tcg_temp_free_i32(mask);
+tcg_temp_free_i64(t0);
+}
+
 static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
 {
 TCGv_i64 t0 = tcg_temp_new_i64();
diff --git a/target/ppc/translate/fp-ops.inc.c 
b/target/ppc/translate/fp-ops.inc.c
index f2bcf0e..88fab65 100644
--- a/target/ppc/translate/fp-ops.inc.c
+++ b/target/ppc/translate/fp-ops.inc.c
@@ -105,6 +105,8 @@ GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x0001, 
PPC_NONE, PPC2_VSX207),
 GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x0001, PPC_NONE, PPC2_VSX207),
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
 GEN_HANDLER_E_2(mffs, 0x3F, 0x07, 0x12, 0x00, 0x, PPC_FLOAT, PPC_NONE),
+GEN_HANDLER_E_2(mffsce, 0x3F, 0x07, 0x12, 0x01, 0x, PPC_FLOAT,
+PPC2_ISA300),
 GEN_HANDLER_E_2(mffsl, 0x3F, 0x07, 0x12, 0x18, 0x, PPC_FLOAT,
 PPC2_ISA300),
 GEN_HANDLER_E_2(mffscrn, 0x3F, 0x07, 0x12, 0x16, 0x, PPC_FLOAT,
-- 
1.8.3.1




[Qemu-devel] [PATCH v2] ppc: Add support for 'mffscrn', 'mffscrni' instructions

2019-09-12 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffscrn' and 'mffscrni' instructions.

'mffscrn' and 'mffscrni' are similar to 'mffsl', except they do not return
the status bits (FI, FR, FPRF) and they also set the rounding mode in the
FPSCR.

On CPUs without support for 'mffscrn'/'mffscrni' (below ISA 3.0), the
instructions will execute identically to 'mffs'.

Signed-off-by: Paul A. Clarke 
---
v2:
- Additionally mask status bits from return value.
- Wrap a couple of too-long lines.

 target/ppc/internal.h  |  3 ++
 target/ppc/translate/fp-impl.inc.c | 67 ++
 target/ppc/translate/fp-ops.inc.c  |  4 +++
 3 files changed, 74 insertions(+)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index d3d327e..15d655b 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -157,6 +157,9 @@ EXTRACT_HELPER(FPL, 25, 1);
 EXTRACT_HELPER(FPFLM, 17, 8);
 EXTRACT_HELPER(FPW, 16, 1);
 
+/* mffscrni */
+EXTRACT_HELPER(RM, 11, 2);
+
 /* addpcis */
 EXTRACT_HELPER_SPLIT_3(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0)
 #if defined(TARGET_PPC64)
diff --git a/target/ppc/translate/fp-impl.inc.c 
b/target/ppc/translate/fp-impl.inc.c
index 7cd9d8d..59a4faf 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -639,6 +639,73 @@ static void gen_mffsl(DisasContext *ctx)
 tcg_temp_free_i64(t0);
 }
 
+static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
+{
+TCGv_i64 t0 = tcg_temp_new_i64();
+TCGv_i32 mask = tcg_const_i32(0x0001);
+
+gen_reset_fpstatus();
+tcg_gen_extu_tl_i64(t0, cpu_fpscr);
+tcg_gen_andi_i64(t0, t0, FP_MODE | FP_ENABLES);
+set_fpr(rD(ctx->opcode), t0);
+
+/* Mask FPSCR value to clear RN.  */
+tcg_gen_andi_i64(t0, t0, ~FP_MODE);
+
+/* Merge RN into FPSCR value.  */
+tcg_gen_or_i64(t0, t0, t1);
+
+gen_helper_store_fpscr(cpu_env, t0, mask);
+
+tcg_temp_free_i32(mask);
+tcg_temp_free_i64(t0);
+}
+
+/* mffscrn */
+static void gen_mffscrn(DisasContext *ctx)
+{
+TCGv_i64 t1;
+
+if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
+return gen_mffs(ctx);
+}
+
+if (unlikely(!ctx->fpu_enabled)) {
+gen_exception(ctx, POWERPC_EXCP_FPU);
+return;
+}
+
+t1 = tcg_temp_new_i64();
+get_fpr(t1, rB(ctx->opcode));
+/* Mask FRB to get just RN.  */
+tcg_gen_andi_i64(t1, t1, FP_MODE);
+
+gen_helper_mffscrn(ctx, t1);
+
+tcg_temp_free_i64(t1);
+}
+
+/* mffscrni */
+static void gen_mffscrni(DisasContext *ctx)
+{
+TCGv_i64 t1;
+
+if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
+return gen_mffs(ctx);
+}
+
+if (unlikely(!ctx->fpu_enabled)) {
+gen_exception(ctx, POWERPC_EXCP_FPU);
+return;
+}
+
+t1 = tcg_const_i64((uint64_t)RM(ctx->opcode));
+
+gen_helper_mffscrn(ctx, t1);
+
+tcg_temp_free_i64(t1);
+}
+
 /* mtfsb0 */
 static void gen_mtfsb0(DisasContext *ctx)
 {
diff --git a/target/ppc/translate/fp-ops.inc.c 
b/target/ppc/translate/fp-ops.inc.c
index 88ebc25..f2bcf0e 100644
--- a/target/ppc/translate/fp-ops.inc.c
+++ b/target/ppc/translate/fp-ops.inc.c
@@ -107,6 +107,10 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, 
PPC_FLOAT),
 GEN_HANDLER_E_2(mffs, 0x3F, 0x07, 0x12, 0x00, 0x, PPC_FLOAT, PPC_NONE),
 GEN_HANDLER_E_2(mffsl, 0x3F, 0x07, 0x12, 0x18, 0x, PPC_FLOAT,
 PPC2_ISA300),
+GEN_HANDLER_E_2(mffscrn, 0x3F, 0x07, 0x12, 0x16, 0x, PPC_FLOAT,
+PPC_NONE),
+GEN_HANDLER_E_2(mffscrni, 0x3F, 0x07, 0x12, 0x17, 0x, PPC_FLOAT,
+PPC_NONE),
 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x, PPC_FLOAT),
-- 
1.8.3.1




[Qemu-devel] [PATCH] ppc: Add support for 'mffscrn', 'mffscrni' instructions

2019-09-11 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffscrn' and 'mffscrni' instructions.

'mffscrn' and 'mffscrni' are identical to 'mffsl', except they also set
the rounding mode in the FPSCR.

On CPUs without support for 'mffscrn'/'mffscrni' (below ISA 3.0), the
instructions will execute identically to 'mffs'.

Signed-off-by: Paul A. Clarke 
---
 target/ppc/internal.h  |  3 ++
 target/ppc/translate/fp-impl.inc.c | 66 ++
 target/ppc/translate/fp-ops.inc.c  |  2 ++
 3 files changed, 71 insertions(+)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index d3d327e..15d655b 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -157,6 +157,9 @@ EXTRACT_HELPER(FPL, 25, 1);
 EXTRACT_HELPER(FPFLM, 17, 8);
 EXTRACT_HELPER(FPW, 16, 1);
 
+/* mffscrni */
+EXTRACT_HELPER(RM, 11, 2);
+
 /* addpcis */
 EXTRACT_HELPER_SPLIT_3(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0)
 #if defined(TARGET_PPC64)
diff --git a/target/ppc/translate/fp-impl.inc.c 
b/target/ppc/translate/fp-impl.inc.c
index 7cd9d8d..70a4788 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -639,6 +639,72 @@ static void gen_mffsl(DisasContext *ctx)
 tcg_temp_free_i64(t0);
 }
 
+static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
+{
+TCGv_i64 t0 = tcg_temp_new_i64();
+TCGv_i32 mask = tcg_const_i32(0x0001);
+
+gen_reset_fpstatus();
+tcg_gen_extu_tl_i64(t0, cpu_fpscr);
+set_fpr(rD(ctx->opcode), t0);
+
+/* Mask FPSCR value to clear RN.  */
+tcg_gen_andi_i64(t0, t0, ~FP_MODE);
+
+/* Merge RN into FPSCR value.  */
+tcg_gen_or_i64(t0, t0, t1);
+
+gen_helper_store_fpscr(cpu_env, t0, mask);
+
+tcg_temp_free_i32(mask);
+tcg_temp_free_i64(t0);
+}
+
+/* mffscrn */
+static void gen_mffscrn(DisasContext *ctx)
+{
+TCGv_i64 t1;
+
+if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
+return gen_mffs(ctx);
+}
+
+if (unlikely(!ctx->fpu_enabled)) {
+gen_exception(ctx, POWERPC_EXCP_FPU);
+return;
+}
+
+t1 = tcg_temp_new_i64();
+get_fpr(t1, rB(ctx->opcode));
+/* Mask FRB to get just RN.  */
+tcg_gen_andi_i64(t1, t1, FP_MODE);
+
+gen_helper_mffscrn(ctx, t1);
+
+tcg_temp_free_i64(t1);
+}
+
+/* mffscrni */
+static void gen_mffscrni(DisasContext *ctx)
+{
+TCGv_i64 t1;
+
+if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
+return gen_mffs(ctx);
+}
+
+if (unlikely(!ctx->fpu_enabled)) {
+gen_exception(ctx, POWERPC_EXCP_FPU);
+return;
+}
+
+t1 = tcg_const_i64((uint64_t)RM(ctx->opcode));
+
+gen_helper_mffscrn(ctx, t1);
+
+tcg_temp_free_i64(t1);
+}
+
 /* mtfsb0 */
 static void gen_mtfsb0(DisasContext *ctx)
 {
diff --git a/target/ppc/translate/fp-ops.inc.c 
b/target/ppc/translate/fp-ops.inc.c
index 88ebc25..598cd53 100644
--- a/target/ppc/translate/fp-ops.inc.c
+++ b/target/ppc/translate/fp-ops.inc.c
@@ -107,6 +107,8 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
 GEN_HANDLER_E_2(mffs, 0x3F, 0x07, 0x12, 0x00, 0x, PPC_FLOAT, PPC_NONE),
 GEN_HANDLER_E_2(mffsl, 0x3F, 0x07, 0x12, 0x18, 0x, PPC_FLOAT,
 PPC2_ISA300),
+GEN_HANDLER_E_2(mffscrn, 0x3F, 0x07, 0x12, 0x16, 0x, PPC_FLOAT, 
PPC_NONE),
+GEN_HANDLER_E_2(mffscrni, 0x3F, 0x07, 0x12, 0x17, 0x, PPC_FLOAT, 
PPC_NONE),
 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x, PPC_FLOAT),
-- 
1.8.3.1




[Qemu-devel] [PATCH] ppc: Fix xsmaddmdp and friends

2019-08-21 Thread Paul A. Clarke
From: "Paul A. Clarke" 

A class of instructions of the form:
  op Target,A,B
which operate like:
  Target = Target * A + B
have a bit set which distinguishes them from instructions that operate as:
  Target = Target * B + A

This bit is not being checked properly (using PPC_BIT macro), so all
instructions in this class are operating incorrectly as the second form
above.  The bit was being checked as if it were part of a 64-bit
instruction opcode, rather than a proper 32-bit opcode.  Fix by using the
macro (PPC_BIT32) which treats the opcode as a 32-bit quantity.

Signed-off-by: Paul A. Clarke 
---
 target/ppc/translate/vsx-impl.inc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/translate/vsx-impl.inc.c 
b/target/ppc/translate/vsx-impl.inc.c
index 3922686..8287e27 100644
--- a/target/ppc/translate/vsx-impl.inc.c
+++ b/target/ppc/translate/vsx-impl.inc.c
@@ -1308,7 +1308,7 @@ static void gen_##name(DisasContext *ctx) 
\
 } \
 xt = gen_vsr_ptr(xT(ctx->opcode));\
 xa = gen_vsr_ptr(xA(ctx->opcode));\
-if (ctx->opcode & PPC_BIT(25)) {  \
+if (ctx->opcode & PPC_BIT32(25)) {\
 /*\
  * AxT + B\
  */   \
-- 
1.8.3.1




[Qemu-devel] [PATCH] ppc: Fix xscvdpspn for SNAN

2019-08-20 Thread Paul A. Clarke
From: "Paul A. Clarke" 

helper_xscvdpspn() uses float64_to_float32() to convert double-precision
floating-point to single-precision.  Unfortunately, float64_to_float32()
converts SNAN to QNAN, which should not happen with xscvdpspn.

float64_to_float32() is also used by other instruction implementations
for conversions which _should_ convert SNAN to QNAN.

Rather than trying to wedge code to preserve SNAN in float64_to_float32()
just for this this one case, I instead embed an embodiment of the
conversion code outlined in the POWER ISA for xscvdpspn.

Signed-off-by: Paul A. Clarke 
---
 target/ppc/fpu_helper.c | 32 ++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 07bc905..c8e7192 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -2887,12 +2887,40 @@ void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode,
 
 uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
 {
-uint64_t result;
+uint64_t result, sign, exp, frac;
 
 float_status tstat = env->fp_status;
 set_float_exception_flags(0, );
 
-result = (uint64_t)float64_to_float32(xb, );
+sign = extract64(xb, 63,  1);
+exp  = extract64(xb, 52, 11);
+frac = extract64(xb,  0, 52) | 0x10ULL;
+
+if (unlikely(exp == 0 && extract64(frac, 0, 52) != 0)) {
+/* DP denormal operand.  */
+/* Exponent override to DP min exp.  */
+exp = 1;
+/* Implicit bit override to 0.  */
+frac = deposit64(frac, 53, 1, 0);
+}
+
+if (unlikely(exp < 897 && frac != 0)) {
+/* SP tiny operand.  */
+if (897 - exp > 63) {
+frac = 0;
+} else {
+/* Denormalize until exp = SP min exp.  */
+frac >>= (897 - exp);
+}
+/* Exponent override to SP min exp - 1.  */
+exp = 896;
+}
+
+result = sign << 31;
+result |= extract64(exp, 10, 1) << 30;
+result |= extract64(exp, 0, 7) << 23;
+result |= extract64(frac, 29, 23);
+
 /* hardware replicates result to both words of the doubleword result.  */
 return (result << 32) | result;
 }
-- 
1.8.3.1




[Qemu-devel] [PATCH v2] ppc: Fix emulated single to double denormalized conversions

2019-08-19 Thread Paul A. Clarke
From: "Paul A. Clarke" 

helper_todouble() was not properly converting any denormalized 32 bit
float to 64 bit double.

Fix-suggested-by: Richard Henderson 
Signed-off-by: Paul A. Clarke 

v2:
- Splitting patch "ppc: Three floating point fixes"; this is just one part.
- Original suggested "fix" was likely flawed.  v2 is rewritten by
  Richard Henderson (Thanks, Richard!); I reformatted the comments in a
  couple of places, compiled, and tested.
---
 target/ppc/fpu_helper.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 52bcda2..07bc905 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -73,11 +73,20 @@ uint64_t helper_todouble(uint32_t arg)
 /* Zero or Denormalized operand.  */
 ret = (uint64_t)extract32(arg, 31, 1) << 63;
 if (unlikely(abs_arg != 0)) {
-/* Denormalized operand.  */
-int shift = clz32(abs_arg) - 9;
-int exp = -126 - shift + 1023;
+/*
+ * Denormalized operand.
+ * Shift fraction so that the msb is in the implicit bit position.
+ * Thus, shift is in the range [1:23].
+ */
+int shift = clz32(abs_arg) - 8;
+/*
+ * The first 3 terms compute the float64 exponent.  We then bias
+ * this result by -1 so that we can swallow the implicit bit below.
+ */
+int exp = -126 - shift + 1023 - 1;
+
 ret |= (uint64_t)exp << 52;
-ret |= abs_arg << (shift + 29);
+ret += (uint64_t)abs_arg << (52 - 23 + shift);
 }
 }
 return ret;
-- 
1.8.3.1




[Qemu-devel] [PATCH] ppc: Fix emulated INFINITY and NAN conversions

2019-08-19 Thread Paul A. Clarke
From: "Paul A. Clarke" 

helper_todouble() was not properly converting INFINITY from 32 bit
float to 64 bit double.

(Normalized operand conversion is unchanged, other than indentation.)

Signed-off-by: Paul A. Clarke 
---
 target/ppc/fpu_helper.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 23b9c97..52bcda2 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -58,10 +58,17 @@ uint64_t helper_todouble(uint32_t arg)
 uint64_t ret;
 
 if (likely(abs_arg >= 0x0080)) {
-/* Normalized operand, or Inf, or NaN.  */
-ret  = (uint64_t)extract32(arg, 30, 2) << 62;
-ret |= ((extract32(arg, 30, 1) ^ 1) * (uint64_t)7) << 59;
-ret |= (uint64_t)extract32(arg, 0, 30) << 29;
+if (unlikely(extract32(arg, 23, 8) == 0xff)) {
+/* Inf or NAN.  */
+ret  = (uint64_t)extract32(arg, 31, 1) << 63;
+ret |= (uint64_t)0x7ff << 52;
+ret |= (uint64_t)extract32(arg, 0, 23) << 29;
+} else {
+/* Normalized operand.  */
+ret  = (uint64_t)extract32(arg, 30, 2) << 62;
+ret |= ((extract32(arg, 30, 1) ^ 1) * (uint64_t)7) << 59;
+ret |= (uint64_t)extract32(arg, 0, 30) << 29;
+}
 } else {
 /* Zero or Denormalized operand.  */
 ret = (uint64_t)extract32(arg, 31, 1) << 63;
-- 
1.8.3.1




[Qemu-devel] [PATCH v2] ppc: conform to processor User's Manual for xscvdpspn

2019-08-19 Thread Paul A. Clarke
From: "Paul A. Clarke" 

The POWER8 and POWER9 User's Manuals specify the implementation
behavior for what the ISA leaves "undefined" behavior for the
xscvdpspn and xscvdpsp instructions.  This patch corrects the QEMU
implementation to match the hardware implementation for that case.

ISA 3.0B has xscvdpspn leaving its result in word 0 of the target register,
with the other words of the target register left "undefined".

The User's Manuals specify:
  VSX scalar convert from double-precision to single-precision (xscvdpsp,
  xscvdpspn).
  VSR[32:63] is set to VSR[0:31].
So, words 0 and 1 both contain the result.

Note: this is important because GCC as of version 8 or so, assumes and takes
advantage of this behavior to optimize the following sequence:
  xscvdpspn vs0,vs1
  mffprwz   r8,f0
ISA 3.0B has xscvdpspn leaving its result in word 0 of the target register,
and mffprwz expecting its input to come from word 1 of the source register.
This sequence fails with QEMU, as a shift is required between those two
instructions.  However, since the hardware splats the result to both words 0
and 1 of its output register, the shift is not necessary.

Expect a future revision of the ISA to specify this behavior.

Signed-off-by: Paul A. Clarke 

v2
- Splitting patch "ppc: Three floating point fixes"; this is just one part.
- Updated commit message to clarify behavior is documented in User's Manuals.
- Updated commit message to correct which words are in output and source of
  xscvdpspn and mffprz.
- No source changes to this part of the original patch.

---
 target/ppc/fpu_helper.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 5611cf0..23b9c97 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -2871,10 +2871,14 @@ void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode,
 
 uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
 {
+uint64_t result;
+
 float_status tstat = env->fp_status;
 set_float_exception_flags(0, );
 
-return (uint64_t)float64_to_float32(xb, ) << 32;
+result = (uint64_t)float64_to_float32(xb, );
+/* hardware replicates result to both words of the doubleword result.  */
+return (result << 32) | result;
 }
 
 uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
-- 
1.8.3.1




[Qemu-devel] [PATCH] ppc: Three floating point fixes

2019-08-16 Thread Paul A. Clarke
From: "Paul A. Clarke" 

- target/ppc/fpu_helper.c:
  - helper_todouble() was not properly converting INFINITY from 32 bit
  float to 64 bit double.
  - helper_todouble() was not properly converting any denormalized
  32 bit float to 64 bit double.

- GCC, as of version 8 or so, takes advantage of the hardware's
  implementation of the xscvdpspn instruction to optimize the following
  sequence:
xscvdpspn vs0,vs1
mffprwz   r8,f0
  ISA 3.0B has xscvdpspn leaving its result in word 1 of the target register,
  and mffprwz expecting its input to come from word 0 of the source register.
  This sequence fails with QEMU, as a shift is required between those two
  instructions.  However, the hardware splats the result to both word 0 and
  word 1 of its output register, so the shift is not necessary.
  Expect a future revision of the ISA to specify this behavior.

Signed-off-by: Paul A. Clarke 
---
 target/ppc/fpu_helper.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 5611cf0..82b5425 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -62,13 +62,14 @@ uint64_t helper_todouble(uint32_t arg)
 ret  = (uint64_t)extract32(arg, 30, 2) << 62;
 ret |= ((extract32(arg, 30, 1) ^ 1) * (uint64_t)7) << 59;
 ret |= (uint64_t)extract32(arg, 0, 30) << 29;
+ret |= (0x7ffULL * (extract32(arg, 23, 8) == 0xff)) << 52;
 } else {
 /* Zero or Denormalized operand.  */
 ret = (uint64_t)extract32(arg, 31, 1) << 63;
 if (unlikely(abs_arg != 0)) {
 /* Denormalized operand.  */
 int shift = clz32(abs_arg) - 9;
-int exp = -126 - shift + 1023;
+int exp = -127 - shift + 1023;
 ret |= (uint64_t)exp << 52;
 ret |= abs_arg << (shift + 29);
 }
@@ -2871,10 +2872,14 @@ void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode,
 
 uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
 {
+uint64_t result;
+
 float_status tstat = env->fp_status;
 set_float_exception_flags(0, );
 
-return (uint64_t)float64_to_float32(xb, ) << 32;
+result = (uint64_t)float64_to_float32(xb, );
+/* hardware replicates result to both words of the doubleword result.  */
+return (result << 32) | result;
 }
 
 uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
-- 
1.8.3.1




[Qemu-devel] [PATCH v4] ppc: Add support for 'mffsl' instruction

2019-08-16 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffsl'.

'mffsl' is identical to 'mffs', except it only returns mode, status, and enable
bits from the FPSCR.

On CPUs without support for 'mffsl' (below ISA 3.0), the 'mffsl' instruction
will execute identically to 'mffs'.

Note: I renamed FPSCR_RN to FPSCR_RN0 so I could create an FPSCR_RN mask which
is both bits of the FPSCR rounding mode, as defined in the ISA.

I also fixed a typo in the definition of FPSCR_FR.

Signed-off-by: Paul A. Clarke 

v4:
- nit: added some braces to resolve a checkpatch complaint.

v3:
- Changed tcg_gen_and_i64 to tcg_gen_andi_i64, eliminating the need for a
  temporary, per review from Richard Henderson.

v2:
- I found that I copied too much of the 'mffs' implementation.
  The 'Rc' condition code bits are not needed for 'mffsl'.  Removed.
- I now free the (renamed) 'tmask' temporary.
- I now bail early for older ISA to the original 'mffs' implementation.

---
 disas/ppc.c|  5 +
 target/ppc/cpu.h   | 15 ++-
 target/ppc/fpu_helper.c|  4 ++--
 target/ppc/translate/fp-impl.inc.c | 22 ++
 target/ppc/translate/fp-ops.inc.c  |  4 +++-
 5 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/disas/ppc.c b/disas/ppc.c
index a545437..63e97cf 100644
--- a/disas/ppc.c
+++ b/disas/ppc.c
@@ -1765,6 +1765,9 @@ extract_tbr (unsigned long insn,
 /* An X_MASK with the RA and RB fields fixed.  */
 #define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
 
+/* An X form instruction with the RA field fixed.  */
+#define XRA(op, xop, ra) (X((op), (xop)) | (((ra) << 16) & XRA_MASK))
+
 /* An XRARB_MASK, but with the L bit clear.  */
 #define XRLARB_MASK (XRARB_MASK & ~((unsigned long) 1 << 16))
 
@@ -4998,6 +5001,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 { "ddivq",   XRC(63,546,0), X_MASK,POWER6, { FRT, FRA, FRB } },
 { "ddivq.",  XRC(63,546,1), X_MASK,POWER6, { FRT, FRA, FRB } },
 
+{ "mffsl",   XRA(63,583,12), XRARB_MASK,   POWER9, { FRT } },
+
 { "mffs",XRC(63,583,0), XRARB_MASK,COM,{ FRT } },
 { "mffs.",   XRC(63,583,1), XRARB_MASK,COM,{ FRT } },
 
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index c9beba2..74e8da4 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -591,7 +591,7 @@ enum {
 #define FPSCR_XE 3  /* Floating-point inexact exception enable   */
 #define FPSCR_NI 2  /* Floating-point non-IEEE mode  */
 #define FPSCR_RN11
-#define FPSCR_RN 0  /* Floating-point rounding control   */
+#define FPSCR_RN00  /* Floating-point rounding control   */
 #define fpscr_fex(((env->fpscr) >> FPSCR_FEX)& 0x1)
 #define fpscr_vx (((env->fpscr) >> FPSCR_VX) & 0x1)
 #define fpscr_ox (((env->fpscr) >> FPSCR_OX) & 0x1)
@@ -614,7 +614,7 @@ enum {
 #define fpscr_ze (((env->fpscr) >> FPSCR_ZE) & 0x1)
 #define fpscr_xe (((env->fpscr) >> FPSCR_XE) & 0x1)
 #define fpscr_ni (((env->fpscr) >> FPSCR_NI) & 0x1)
-#define fpscr_rn (((env->fpscr) >> FPSCR_RN) & 0x3)
+#define fpscr_rn (((env->fpscr) >> FPSCR_RN0)& 0x3)
 /* Invalid operation exception summary */
 #define fpscr_ix ((env->fpscr) & ((1 << FPSCR_VXSNAN) | (1 << FPSCR_VXISI)  | \
   (1 << FPSCR_VXIDI)  | (1 << FPSCR_VXZDZ)  | \
@@ -640,7 +640,7 @@ enum {
 #define FP_VXZDZ(1ull << FPSCR_VXZDZ)
 #define FP_VXIMZ(1ull << FPSCR_VXIMZ)
 #define FP_VXVC (1ull << FPSCR_VXVC)
-#define FP_FR   (1ull << FSPCR_FR)
+#define FP_FR   (1ull << FPSCR_FR)
 #define FP_FI   (1ull << FPSCR_FI)
 #define FP_C(1ull << FPSCR_C)
 #define FP_FL   (1ull << FPSCR_FL)
@@ -648,7 +648,7 @@ enum {
 #define FP_FE   (1ull << FPSCR_FE)
 #define FP_FU   (1ull << FPSCR_FU)
 #define FP_FPCC (FP_FL | FP_FG | FP_FE | FP_FU)
-#define FP_FPRF (FP_C  | FP_FL | FP_FG | FP_FE | FP_FU)
+#define FP_FPRF (FP_C | FP_FPCC)
 #define FP_VXSOFT   (1ull << FPSCR_VXSOFT)
 #define FP_VXSQRT   (1ull << FPSCR_VXSQRT)
 #define FP_VXCVI(1ull << FPSCR_VXCVI)
@@ -659,7 +659,12 @@ enum {
 #define FP_XE   (1ull << FPSCR_XE)
 #define FP_NI   (1ull << FPSCR_NI)
 #define FP_RN1  (1ull << FPSCR_RN1)
-#define FP_RN   (1ull << FPSCR_RN)
+#define FP_RN0  (1ull << FPSCR_RN0)
+#define FP_RN   (FP

[Qemu-devel] [PATCH v3] ppc: Add support for 'mffsl' instruction

2019-08-14 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffsl'.

'mffsl' is identical to 'mffs', except it only returns mode, status, and enable
bits from the FPSCR.

On CPUs without support for 'mffsl' (below ISA 3.0), the 'mffsl' instruction
will execute identically to 'mffs'.

Note: I renamed FPSCR_RN to FPSCR_RN0 so I could create an FPSCR_RN mask which
is both bits of the FPSCR rounding mode, as defined in the ISA.

I also fixed a typo in the definition of FPSCR_FR.

Signed-off-by: Paul A. Clarke 

v3:
- Changed tcg_gen_and_i64 to tcg_gen_andi_i64, eliminating the need for a
  temporary, per review from Richard Henderson.

v2:
- I found that I copied too much of the 'mffs' implementation.
  The 'Rc' condition code bits are not needed for 'mffsl'.  Removed.
- I now free the (renamed) 'tmask' temporary.
- I now bail early for older ISA to the original 'mffs' implementation.

---
 disas/ppc.c|  5 +
 target/ppc/cpu.h   | 15 ++-
 target/ppc/fpu_helper.c|  4 ++--
 target/ppc/translate/fp-impl.inc.c | 21 +
 target/ppc/translate/fp-ops.inc.c  |  4 +++-
 5 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/disas/ppc.c b/disas/ppc.c
index a545437..63e97cf 100644
--- a/disas/ppc.c
+++ b/disas/ppc.c
@@ -1765,6 +1765,9 @@ extract_tbr (unsigned long insn,
 /* An X_MASK with the RA and RB fields fixed.  */
 #define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
 
+/* An X form instruction with the RA field fixed.  */
+#define XRA(op, xop, ra) (X((op), (xop)) | (((ra) << 16) & XRA_MASK))
+
 /* An XRARB_MASK, but with the L bit clear.  */
 #define XRLARB_MASK (XRARB_MASK & ~((unsigned long) 1 << 16))
 
@@ -4998,6 +5001,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 { "ddivq",   XRC(63,546,0), X_MASK,POWER6, { FRT, FRA, FRB } },
 { "ddivq.",  XRC(63,546,1), X_MASK,POWER6, { FRT, FRA, FRB } },
 
+{ "mffsl",   XRA(63,583,12), XRARB_MASK,   POWER9, { FRT } },
+
 { "mffs",XRC(63,583,0), XRARB_MASK,COM,{ FRT } },
 { "mffs.",   XRC(63,583,1), XRARB_MASK,COM,{ FRT } },
 
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index c9beba2..74e8da4 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -591,7 +591,7 @@ enum {
 #define FPSCR_XE 3  /* Floating-point inexact exception enable   */
 #define FPSCR_NI 2  /* Floating-point non-IEEE mode  */
 #define FPSCR_RN11
-#define FPSCR_RN 0  /* Floating-point rounding control   */
+#define FPSCR_RN00  /* Floating-point rounding control   */
 #define fpscr_fex(((env->fpscr) >> FPSCR_FEX)& 0x1)
 #define fpscr_vx (((env->fpscr) >> FPSCR_VX) & 0x1)
 #define fpscr_ox (((env->fpscr) >> FPSCR_OX) & 0x1)
@@ -614,7 +614,7 @@ enum {
 #define fpscr_ze (((env->fpscr) >> FPSCR_ZE) & 0x1)
 #define fpscr_xe (((env->fpscr) >> FPSCR_XE) & 0x1)
 #define fpscr_ni (((env->fpscr) >> FPSCR_NI) & 0x1)
-#define fpscr_rn (((env->fpscr) >> FPSCR_RN) & 0x3)
+#define fpscr_rn (((env->fpscr) >> FPSCR_RN0)& 0x3)
 /* Invalid operation exception summary */
 #define fpscr_ix ((env->fpscr) & ((1 << FPSCR_VXSNAN) | (1 << FPSCR_VXISI)  | \
   (1 << FPSCR_VXIDI)  | (1 << FPSCR_VXZDZ)  | \
@@ -640,7 +640,7 @@ enum {
 #define FP_VXZDZ(1ull << FPSCR_VXZDZ)
 #define FP_VXIMZ(1ull << FPSCR_VXIMZ)
 #define FP_VXVC (1ull << FPSCR_VXVC)
-#define FP_FR   (1ull << FSPCR_FR)
+#define FP_FR   (1ull << FPSCR_FR)
 #define FP_FI   (1ull << FPSCR_FI)
 #define FP_C(1ull << FPSCR_C)
 #define FP_FL   (1ull << FPSCR_FL)
@@ -648,7 +648,7 @@ enum {
 #define FP_FE   (1ull << FPSCR_FE)
 #define FP_FU   (1ull << FPSCR_FU)
 #define FP_FPCC (FP_FL | FP_FG | FP_FE | FP_FU)
-#define FP_FPRF (FP_C  | FP_FL | FP_FG | FP_FE | FP_FU)
+#define FP_FPRF (FP_C | FP_FPCC)
 #define FP_VXSOFT   (1ull << FPSCR_VXSOFT)
 #define FP_VXSQRT   (1ull << FPSCR_VXSQRT)
 #define FP_VXCVI(1ull << FPSCR_VXCVI)
@@ -659,7 +659,12 @@ enum {
 #define FP_XE   (1ull << FPSCR_XE)
 #define FP_NI   (1ull << FPSCR_NI)
 #define FP_RN1  (1ull << FPSCR_RN1)
-#define FP_RN   (1ull << FPSCR_RN)
+#define FP_RN0  (1ull << FPSCR_RN0)
+#define FP_RN   (FP_RN1 | FP_RN0)
+
+#define FP_MODE FP_RN
+#define FP_ENABLE

[Qemu-devel] [PATCH v2] ppc: Add support for 'mffsl' instruction

2019-08-13 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffsl'.

'mffsl' is identical to 'mffs', except it only returns mode, status, and enable
bits from the FPSCR.

On CPUs without support for 'mffsl' (below ISA 3.0), the 'mffsl' instruction
will execute identically to 'mffs'.

Note: I renamed FPSCR_RN to FPSCR_RN0 so I could create an FPSCR_RN mask which
is both bits of the FPSCR rounding mode, as defined in the ISA.

I also fixed a typo in the definition of FPSCR_FR.

Signed-off-by: Paul A. Clarke 

v2: (Sorry for the quick v2!)
- I found that I copied too much of the 'mffs' implementation.
  The 'Rc' condition code bits are not needed for 'mffsl'.  Removed.
- I now free the (renamed) 'tmask' temporary.
- I now bail early for older ISA to the original 'mffs' implementation.

---
 disas/ppc.c|  5 +
 target/ppc/cpu.h   | 15 ++-
 target/ppc/fpu_helper.c|  4 ++--
 target/ppc/translate/fp-impl.inc.c | 23 +++
 target/ppc/translate/fp-ops.inc.c  |  3 ++-
 5 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/disas/ppc.c b/disas/ppc.c
index a545437..12b6a14 100644
--- a/disas/ppc.c
+++ b/disas/ppc.c
@@ -1765,6 +1765,9 @@ extract_tbr (unsigned long insn,
 /* An X_MASK with the RA and RB fields fixed.  */
 #define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
 
+/* An X form instruction with the RA field fixed.  */
+#define XRA(op, xop, ra) (X ((op), (xop)) | (((ra) << 16) & XRA_MASK))
+
 /* An XRARB_MASK, but with the L bit clear.  */
 #define XRLARB_MASK (XRARB_MASK & ~((unsigned long) 1 << 16))
 
@@ -4998,6 +5001,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 { "ddivq",   XRC(63,546,0), X_MASK,POWER6, { FRT, FRA, FRB } },
 { "ddivq.",  XRC(63,546,1), X_MASK,POWER6, { FRT, FRA, FRB } },
 
+{ "mffsl",   XRA(63,583,12), XRARB_MASK,   POWER9, { FRT } },
+
 { "mffs",XRC(63,583,0), XRARB_MASK,COM,{ FRT } },
 { "mffs.",   XRC(63,583,1), XRARB_MASK,COM,{ FRT } },
 
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index c9beba2..74e8da4 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -591,7 +591,7 @@ enum {
 #define FPSCR_XE 3  /* Floating-point inexact exception enable   */
 #define FPSCR_NI 2  /* Floating-point non-IEEE mode  */
 #define FPSCR_RN11
-#define FPSCR_RN 0  /* Floating-point rounding control   */
+#define FPSCR_RN00  /* Floating-point rounding control   */
 #define fpscr_fex(((env->fpscr) >> FPSCR_FEX)& 0x1)
 #define fpscr_vx (((env->fpscr) >> FPSCR_VX) & 0x1)
 #define fpscr_ox (((env->fpscr) >> FPSCR_OX) & 0x1)
@@ -614,7 +614,7 @@ enum {
 #define fpscr_ze (((env->fpscr) >> FPSCR_ZE) & 0x1)
 #define fpscr_xe (((env->fpscr) >> FPSCR_XE) & 0x1)
 #define fpscr_ni (((env->fpscr) >> FPSCR_NI) & 0x1)
-#define fpscr_rn (((env->fpscr) >> FPSCR_RN) & 0x3)
+#define fpscr_rn (((env->fpscr) >> FPSCR_RN0)& 0x3)
 /* Invalid operation exception summary */
 #define fpscr_ix ((env->fpscr) & ((1 << FPSCR_VXSNAN) | (1 << FPSCR_VXISI)  | \
   (1 << FPSCR_VXIDI)  | (1 << FPSCR_VXZDZ)  | \
@@ -640,7 +640,7 @@ enum {
 #define FP_VXZDZ(1ull << FPSCR_VXZDZ)
 #define FP_VXIMZ(1ull << FPSCR_VXIMZ)
 #define FP_VXVC (1ull << FPSCR_VXVC)
-#define FP_FR   (1ull << FSPCR_FR)
+#define FP_FR   (1ull << FPSCR_FR)
 #define FP_FI   (1ull << FPSCR_FI)
 #define FP_C(1ull << FPSCR_C)
 #define FP_FL   (1ull << FPSCR_FL)
@@ -648,7 +648,7 @@ enum {
 #define FP_FE   (1ull << FPSCR_FE)
 #define FP_FU   (1ull << FPSCR_FU)
 #define FP_FPCC (FP_FL | FP_FG | FP_FE | FP_FU)
-#define FP_FPRF (FP_C  | FP_FL | FP_FG | FP_FE | FP_FU)
+#define FP_FPRF (FP_C | FP_FPCC)
 #define FP_VXSOFT   (1ull << FPSCR_VXSOFT)
 #define FP_VXSQRT   (1ull << FPSCR_VXSQRT)
 #define FP_VXCVI(1ull << FPSCR_VXCVI)
@@ -659,7 +659,12 @@ enum {
 #define FP_XE   (1ull << FPSCR_XE)
 #define FP_NI   (1ull << FPSCR_NI)
 #define FP_RN1  (1ull << FPSCR_RN1)
-#define FP_RN   (1ull << FPSCR_RN)
+#define FP_RN0  (1ull << FPSCR_RN0)
+#define FP_RN   (FP_RN1 | FP_RN0)
+
+#define FP_MODE FP_RN
+#define FP_ENABLES  (FP_VE | FP_OE | FP_UE | FP_ZE | FP_XE)
+#define FP_STATUS   (FP_FR | FP_FI | FP_FPRF)
 
 

[Qemu-devel] [PATCH] ppc: Add support for 'mffsl' instruction

2019-08-13 Thread Paul A. Clarke
From: "Paul A. Clarke" 

ISA 3.0B added a set of Floating-Point Status and Control Register (FPSCR)
instructions: mffsce, mffscdrn, mffscdrni, mffscrn, mffscrni, mffsl.
This patch adds support for 'mffsl'.

'mffsl' is identical to 'mffs', except it only returns mode, status, and enable
bits from the FPSCR.

On CPUs without support for 'mffsl' (below ISA 3.0), the 'mffsl' instruction
will execute identically to 'mffs'.

Note: I renamed FPSCR_RN to FPSCR_RN0 so I could create an FPSCR_RN mask which
is both bits of the FPSCR rounding mode, as defined in the ISA.

I also fixed a typo in the definition of FPSCR_FR.

Signed-off-by: Paul A. Clarke 
---
 disas/ppc.c|  5 +
 target/ppc/cpu.h   | 15 ++-
 target/ppc/fpu_helper.c|  4 ++--
 target/ppc/translate/fp-impl.inc.c | 23 +++
 target/ppc/translate/fp-ops.inc.c  |  3 ++-
 5 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/disas/ppc.c b/disas/ppc.c
index a545437..12b6a14 100644
--- a/disas/ppc.c
+++ b/disas/ppc.c
@@ -1765,6 +1765,9 @@ extract_tbr (unsigned long insn,
 /* An X_MASK with the RA and RB fields fixed.  */
 #define XRARB_MASK (X_MASK | RA_MASK | RB_MASK)
 
+/* An X form instruction with the RA field fixed.  */
+#define XRA(op, xop, ra) (X ((op), (xop)) | (((ra) << 16) & XRA_MASK))
+
 /* An XRARB_MASK, but with the L bit clear.  */
 #define XRLARB_MASK (XRARB_MASK & ~((unsigned long) 1 << 16))
 
@@ -4998,6 +5001,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 { "ddivq",   XRC(63,546,0), X_MASK,POWER6, { FRT, FRA, FRB } },
 { "ddivq.",  XRC(63,546,1), X_MASK,POWER6, { FRT, FRA, FRB } },
 
+{ "mffsl",   XRA(63,583,12), XRARB_MASK,   POWER9, { FRT } },
+
 { "mffs",XRC(63,583,0), XRARB_MASK,COM,{ FRT } },
 { "mffs.",   XRC(63,583,1), XRARB_MASK,COM,{ FRT } },
 
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index c9beba2..74e8da4 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -591,7 +591,7 @@ enum {
 #define FPSCR_XE 3  /* Floating-point inexact exception enable   */
 #define FPSCR_NI 2  /* Floating-point non-IEEE mode  */
 #define FPSCR_RN11
-#define FPSCR_RN 0  /* Floating-point rounding control   */
+#define FPSCR_RN00  /* Floating-point rounding control   */
 #define fpscr_fex(((env->fpscr) >> FPSCR_FEX)& 0x1)
 #define fpscr_vx (((env->fpscr) >> FPSCR_VX) & 0x1)
 #define fpscr_ox (((env->fpscr) >> FPSCR_OX) & 0x1)
@@ -614,7 +614,7 @@ enum {
 #define fpscr_ze (((env->fpscr) >> FPSCR_ZE) & 0x1)
 #define fpscr_xe (((env->fpscr) >> FPSCR_XE) & 0x1)
 #define fpscr_ni (((env->fpscr) >> FPSCR_NI) & 0x1)
-#define fpscr_rn (((env->fpscr) >> FPSCR_RN) & 0x3)
+#define fpscr_rn (((env->fpscr) >> FPSCR_RN0)& 0x3)
 /* Invalid operation exception summary */
 #define fpscr_ix ((env->fpscr) & ((1 << FPSCR_VXSNAN) | (1 << FPSCR_VXISI)  | \
   (1 << FPSCR_VXIDI)  | (1 << FPSCR_VXZDZ)  | \
@@ -640,7 +640,7 @@ enum {
 #define FP_VXZDZ(1ull << FPSCR_VXZDZ)
 #define FP_VXIMZ(1ull << FPSCR_VXIMZ)
 #define FP_VXVC (1ull << FPSCR_VXVC)
-#define FP_FR   (1ull << FSPCR_FR)
+#define FP_FR   (1ull << FPSCR_FR)
 #define FP_FI   (1ull << FPSCR_FI)
 #define FP_C(1ull << FPSCR_C)
 #define FP_FL   (1ull << FPSCR_FL)
@@ -648,7 +648,7 @@ enum {
 #define FP_FE   (1ull << FPSCR_FE)
 #define FP_FU   (1ull << FPSCR_FU)
 #define FP_FPCC (FP_FL | FP_FG | FP_FE | FP_FU)
-#define FP_FPRF (FP_C  | FP_FL | FP_FG | FP_FE | FP_FU)
+#define FP_FPRF (FP_C | FP_FPCC)
 #define FP_VXSOFT   (1ull << FPSCR_VXSOFT)
 #define FP_VXSQRT   (1ull << FPSCR_VXSQRT)
 #define FP_VXCVI(1ull << FPSCR_VXCVI)
@@ -659,7 +659,12 @@ enum {
 #define FP_XE   (1ull << FPSCR_XE)
 #define FP_NI   (1ull << FPSCR_NI)
 #define FP_RN1  (1ull << FPSCR_RN1)
-#define FP_RN   (1ull << FPSCR_RN)
+#define FP_RN0  (1ull << FPSCR_RN0)
+#define FP_RN   (FP_RN1 | FP_RN0)
+
+#define FP_MODE FP_RN
+#define FP_ENABLES  (FP_VE | FP_OE | FP_UE | FP_ZE | FP_XE)
+#define FP_STATUS   (FP_FR | FP_FI | FP_FPRF)
 
 /* the exception bits which can be cleared by mcrfs - includes FX */
 #define FP_EX_CLEAR_BITS (FP_FX | FP_OX | FP_UX | FP_ZX | \
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index f437c88..5611cf0 100644
--- a/target/ppc/fpu_helper.c
+++ b/targe