diff mbox series

[04/19] target/ppc: Set result to QNaN for DENBCD when VXCVI occurs

Message ID 20220901131756.26060-5-victor.colombo@eldorado.org.br (mailing list archive)
State New, archived
Headers show
Series Multiple ppc instructions fixes | expand

Commit Message

Víctor Colombo Sept. 1, 2022, 1:17 p.m. UTC
According to the ISA, for instruction DENBCD:
"If an invalid BCD digit or sign code is detected in the source
operand, an invalid-operation exception (VXCVI) occurs."

In the Invalid Operation Exception section, there is the situation:
"When Invalid Operation Exception is disabled (VE=0) and Invalid
Operation occurs (...) If the operation is an (...) or format the
target FPR is set to a Quiet NaN". This was not being done in
QEMU.

This patch sets the result to QNaN when the instruction DENBCD causes
an Invalid Operation Exception.

Signed-off-by: Víctor Colombo <victor.colombo@eldorado.org.br>
---
 target/ppc/dfp_helper.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

Comments

Daniel Henrique Barboza Sept. 5, 2022, 6:21 p.m. UTC | #1
On 9/1/22 10:17, Víctor Colombo wrote:
> According to the ISA, for instruction DENBCD:
> "If an invalid BCD digit or sign code is detected in the source
> operand, an invalid-operation exception (VXCVI) occurs."
> 
> In the Invalid Operation Exception section, there is the situation:
> "When Invalid Operation Exception is disabled (VE=0) and Invalid
> Operation occurs (...) If the operation is an (...) or format the
> target FPR is set to a Quiet NaN". This was not being done in
> QEMU.
> 
> This patch sets the result to QNaN when the instruction DENBCD causes
> an Invalid Operation Exception.
> 
> Signed-off-by: Víctor Colombo <victor.colombo@eldorado.org.br>
> ---

Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>

>   target/ppc/dfp_helper.c | 26 ++++++++++++++++++++++++--
>   1 file changed, 24 insertions(+), 2 deletions(-)
> 
> diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c
> index be7aa5357a..cc024316d5 100644
> --- a/target/ppc/dfp_helper.c
> +++ b/target/ppc/dfp_helper.c
> @@ -1147,6 +1147,26 @@ static inline uint8_t dfp_get_bcd_digit_128(ppc_vsr_t *t, unsigned n)
>       return t->VsrD((n & 0x10) ? 0 : 1) >> ((n << 2) & 63) & 15;
>   }
>   
> +static inline void dfp_invalid_op_vxcvi_64(struct PPC_DFP *dfp)
> +{
> +    /* TODO: fpscr is incorrectly not being saved to env */
> +    dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
> +    if ((dfp->env->fpscr & FP_VE) == 0) {
> +        dfp->vt.VsrD(1) = 0x7c00000000000000; /* QNaN */
> +    }
> +}
> +
> +
> +static inline void dfp_invalid_op_vxcvi_128(struct PPC_DFP *dfp)
> +{
> +    /* TODO: fpscr is incorrectly not being saved to env */
> +    dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
> +    if ((dfp->env->fpscr & FP_VE) == 0) {
> +        dfp->vt.VsrD(0) = 0x7c00000000000000; /* QNaN */
> +        dfp->vt.VsrD(1) = 0x0;
> +    }
> +}
> +
>   #define DFP_HELPER_ENBCD(op, size)                                           \
>   void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,             \
>                    uint32_t s)                                                 \
> @@ -1173,7 +1193,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,             \
>               sgn = 0;                                                         \
>               break;                                                           \
>           default:                                                             \
> -            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
> +            dfp_invalid_op_vxcvi_##size(&dfp);                               \
> +            set_dfp##size(t, &dfp.vt);                                       \
>               return;                                                          \
>           }                                                                    \
>           }                                                                    \
> @@ -1183,7 +1204,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,             \
>           digits[(size) / 4 - n] = dfp_get_bcd_digit_##size(&dfp.vb,           \
>                                                             offset++);         \
>           if (digits[(size) / 4 - n] > 10) {                                   \
> -            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
> +            dfp_invalid_op_vxcvi_##size(&dfp);                               \
> +            set_dfp##size(t, &dfp.vt);                                       \
>               return;                                                          \
>           } else {                                                             \
>               nonzero |= (digits[(size) / 4 - n] > 0);                         \
diff mbox series

Patch

diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c
index be7aa5357a..cc024316d5 100644
--- a/target/ppc/dfp_helper.c
+++ b/target/ppc/dfp_helper.c
@@ -1147,6 +1147,26 @@  static inline uint8_t dfp_get_bcd_digit_128(ppc_vsr_t *t, unsigned n)
     return t->VsrD((n & 0x10) ? 0 : 1) >> ((n << 2) & 63) & 15;
 }
 
+static inline void dfp_invalid_op_vxcvi_64(struct PPC_DFP *dfp)
+{
+    /* TODO: fpscr is incorrectly not being saved to env */
+    dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
+    if ((dfp->env->fpscr & FP_VE) == 0) {
+        dfp->vt.VsrD(1) = 0x7c00000000000000; /* QNaN */
+    }
+}
+
+
+static inline void dfp_invalid_op_vxcvi_128(struct PPC_DFP *dfp)
+{
+    /* TODO: fpscr is incorrectly not being saved to env */
+    dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
+    if ((dfp->env->fpscr & FP_VE) == 0) {
+        dfp->vt.VsrD(0) = 0x7c00000000000000; /* QNaN */
+        dfp->vt.VsrD(1) = 0x0;
+    }
+}
+
 #define DFP_HELPER_ENBCD(op, size)                                           \
 void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,             \
                  uint32_t s)                                                 \
@@ -1173,7 +1193,8 @@  void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,             \
             sgn = 0;                                                         \
             break;                                                           \
         default:                                                             \
-            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
+            dfp_invalid_op_vxcvi_##size(&dfp);                               \
+            set_dfp##size(t, &dfp.vt);                                       \
             return;                                                          \
         }                                                                    \
         }                                                                    \
@@ -1183,7 +1204,8 @@  void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b,             \
         digits[(size) / 4 - n] = dfp_get_bcd_digit_##size(&dfp.vb,           \
                                                           offset++);         \
         if (digits[(size) / 4 - n] > 10) {                                   \
-            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
+            dfp_invalid_op_vxcvi_##size(&dfp);                               \
+            set_dfp##size(t, &dfp.vt);                                       \
             return;                                                          \
         } else {                                                             \
             nonzero |= (digits[(size) / 4 - n] > 0);                         \