* [Qemu-devel] [V2 PATCH 01/18] target-ppc: Add Flag for Power ISA V2.06
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 02/18] target-ppc: Add ISA2.06 bpermd Instruction Tom Musta
` (17 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds a flag for base instruction additions to Power ISA
2.06B. The flag will be used to identify/select basic Book I and
Book II instructions that were newly added in that revision of the
architecture. The flag will not be used for VSX or Altivec.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/cpu.h | 4 +++-
target-ppc/translate_init.c | 6 ++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 0abc848..fe3aace 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1877,9 +1877,11 @@ enum {
PPC2_ISA205 = 0x0000000000000020ULL,
/* VSX additions in ISA 2.07 */
PPC2_VSX207 = 0x0000000000000040ULL,
+ /* Book I 2.06B PowerPC specification (base instructions) */
+ PPC2_ISA206 = 0x0000000000000080ULL,
#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \
- PPC2_ISA205 | PPC2_VSX207)
+ PPC2_ISA205 | PPC2_VSX207 | PPC2_ISA206)
};
/*****************************************************************************/
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e14ab63..491e56c 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7234,7 +7234,8 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
PPC_64B | PPC_ALTIVEC |
PPC_SEGMENT_64B | PPC_SLBI |
PPC_POPCNTB | PPC_POPCNTWD;
- pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205;
+ pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205 |
+ PPC2_ISA206;
pcc->msr_mask = 0x800000000284FF37ULL;
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
@@ -7270,7 +7271,8 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
PPC_64B | PPC_ALTIVEC |
PPC_SEGMENT_64B | PPC_SLBI |
PPC_POPCNTB | PPC_POPCNTWD;
- pcc->insns_flags2 = PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX;
+ pcc->insns_flags2 = PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX |
+ PPC2_ISA206;
pcc->msr_mask = 0x800000000284FF36ULL;
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 02/18] target-ppc: Add ISA2.06 bpermd Instruction
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 01/18] target-ppc: Add Flag for Power ISA V2.06 Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 21:19 ` Richard Henderson
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 03/18] target-ppc: Add ISA2.06 divdeu[o] Instructions Tom Musta
` (16 subsequent siblings)
18 siblings, 1 reply; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the Bit Permute Doubleword (bpermd) instruction,
which was introduced in Power ISA 2.06 as part of the base 64-bit
architecture.
V2: Addressing stylistic comments from Richard Henderson.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/helper.h | 1 +
target-ppc/int_helper.c | 20 ++++++++++++++++++++
target-ppc/translate.c | 10 ++++++++++
3 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 6250eba..1ec9c65 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -41,6 +41,7 @@ DEF_HELPER_3(sraw, tl, env, tl, tl)
#if defined(TARGET_PPC64)
DEF_HELPER_FLAGS_1(cntlzd, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_1(popcntd, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_3(bpermd, i64, env, i64, i64)
DEF_HELPER_3(srad, tl, env, tl, tl)
#endif
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index e50bdd2..abc69a7 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -53,6 +53,26 @@ target_ulong helper_cntlzd(target_ulong t)
}
#endif
+#if defined(TARGET_PPC64)
+
+uint64_t helper_bpermd(CPUPPCState *env, uint64_t rs, uint64_t rb)
+{
+ int i;
+ uint64_t ra = 0;
+
+ for (i = 0; i < 8; i++) {
+ int index = (rs >> (i*8)) & 0xFF;
+ if (index < 64) {
+ if (rb & (1ul << (63-index))) {
+ ra |= 1 << i;
+ }
+ }
+ }
+ return ra;
+}
+
+#endif
+
target_ulong helper_cmpb(target_ulong rs, target_ulong rb)
{
target_ulong mask = 0xff;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 1f7e499..0d39de2 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -1525,6 +1525,15 @@ static void gen_prtyd(DisasContext *ctx)
#endif
#if defined(TARGET_PPC64)
+/* bpermd */
+static void gen_bpermd(DisasContext *ctx)
+{
+ gen_helper_bpermd(cpu_gpr[rA(ctx->opcode)], cpu_env,
+ cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
+}
+#endif
+
+#if defined(TARGET_PPC64)
/* extsw & extsw. */
GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
@@ -9322,6 +9331,7 @@ GEN_HANDLER_E(prtyw, 0x1F, 0x1A, 0x04, 0x0000F801, PPC_NONE, PPC2_ISA205),
GEN_HANDLER(popcntd, 0x1F, 0x1A, 0x0F, 0x0000F801, PPC_POPCNTWD),
GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B),
GEN_HANDLER_E(prtyd, 0x1F, 0x1A, 0x05, 0x0000F801, PPC_NONE, PPC2_ISA205),
+GEN_HANDLER_E(bpermd, 0x1F, 0x1C, 0x07, 0x00000001, PPC_NONE, PPC2_ISA206),
#endif
GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 02/18] target-ppc: Add ISA2.06 bpermd Instruction
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 02/18] target-ppc: Add ISA2.06 bpermd Instruction Tom Musta
@ 2013-12-11 21:19 ` Richard Henderson
0 siblings, 0 replies; 31+ messages in thread
From: Richard Henderson @ 2013-12-11 21:19 UTC (permalink / raw)
To: Tom Musta, qemu-devel; +Cc: qemu-ppc
On 12/11/2013 11:16 AM, Tom Musta wrote:
> This patch adds the Bit Permute Doubleword (bpermd) instruction,
> which was introduced in Power ISA 2.06 as part of the base 64-bit
> architecture.
>
> V2: Addressing stylistic comments from Richard Henderson.
>
> Signed-off-by: Tom Musta <tommusta@gmail.com>
> ---
> target-ppc/helper.h | 1 +
> target-ppc/int_helper.c | 20 ++++++++++++++++++++
> target-ppc/translate.c | 10 ++++++++++
> 3 files changed, 31 insertions(+), 0 deletions(-)
Reviewed-by: Richard Henderson <rth@twiddle.net>
r~
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 03/18] target-ppc: Add ISA2.06 divdeu[o] Instructions
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 01/18] target-ppc: Add Flag for Power ISA V2.06 Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 02/18] target-ppc: Add ISA2.06 bpermd Instruction Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 04/18] target-ppc: Add ISA2.06 divde[o] Instructions Tom Musta
` (15 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the Divide Doubleword Extended Unsigned
instructions. This instruction requires dividing a 128-bit
value by a 64 bit value. Since 128 bit integer division is
not supported in TCG, a helper is used, providing a
repeated difference algorithm.
V2: Moved the 128-bit divide routine into host-utils per Richard
Henderson's suggestion.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
include/qemu/host-utils.h | 14 ++++++++++++++
target-ppc/helper.h | 1 +
target-ppc/int_helper.c | 27 +++++++++++++++++++++++++++
target-ppc/translate.c | 20 ++++++++++++++++++++
util/host-utils.c | 38 ++++++++++++++++++++++++++++++++++++++
5 files changed, 100 insertions(+), 0 deletions(-)
diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
index 0f688c1..0ca187d 100644
--- a/include/qemu/host-utils.h
+++ b/include/qemu/host-utils.h
@@ -44,9 +44,23 @@ static inline void muls64(uint64_t *plow, uint64_t *phigh,
*plow = r;
*phigh = r >> 64;
}
+
+static inline int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
+{
+ if (divisor == 0) {
+ return 1;
+ } else {
+ __uint128_t dividend = ((__uint128_t)*phigh << 64) | *plow;
+ __uint128_t result = dividend / divisor;
+ *plow = result;
+ *phigh = dividend % divisor;
+ return result > UINT64_MAX;
+ }
+}
#else
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
+int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
#endif
/**
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 1ec9c65..3eff4df 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -31,6 +31,7 @@ DEF_HELPER_5(lscbx, tl, env, tl, i32, i32, i32)
#if defined(TARGET_PPC64)
DEF_HELPER_3(mulldo, i64, env, i64, i64)
+DEF_HELPER_4(divdeu, i64, env, i64, i64, i32)
#endif
DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_NO_RWG_SE, tl, tl)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index abc69a7..d6dcac9 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -41,6 +41,33 @@ uint64_t helper_mulldo(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
}
#endif
+#if defined(TARGET_PPC64)
+
+uint64_t helper_divdeu(CPUPPCState *env, uint64_t ra, uint64_t rb, uint32_t oe)
+{
+ uint64_t rt = 0;
+ int overflow = 0;
+
+ overflow = divu128(&rt, &ra, rb);
+
+ if (unlikely(overflow)) {
+ rt = 0; /* Undefined */
+ }
+
+ if (oe) {
+ if (unlikely(overflow)) {
+ env->so = env->ov = 1;
+ } else {
+ env->ov = 0;
+ }
+ }
+
+ return rt;
+}
+
+#endif
+
+
target_ulong helper_cntlzw(target_ulong t)
{
return clz32(t);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 0d39de2..7a51c6d 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -1032,6 +1032,23 @@ GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
/* divw divw. divwo divwo. */
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
+
+/* divdeu[o][.] */
+#define GEN_DIVDE(name, hlpr, compute_ov) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv_i32 t0 = tcg_const_i32(compute_ov); \
+ gen_helper_##hlpr(cpu_gpr[rD(ctx->opcode)], cpu_env, \
+ cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0); \
+ tcg_temp_free_i32(t0); \
+ if (unlikely(Rc(ctx->opcode) != 0)) { \
+ gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); \
+ } \
+}
+
+GEN_DIVDE(divdeu, divdeu, 0);
+GEN_DIVDE(divdeuo, divdeu, 1);
+
#endif
/* mulhw mulhw. */
@@ -9594,6 +9611,9 @@ GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1),
GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0),
GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
+GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0x00000000, PPC_NONE, PPC2_ISA206),
+
#undef GEN_INT_ARITH_MUL_HELPER
#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B)
diff --git a/util/host-utils.c b/util/host-utils.c
index f0784d6..b6f7a6e 100644
--- a/util/host-utils.c
+++ b/util/host-utils.c
@@ -86,4 +86,42 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
}
*phigh = rh;
}
+
+/* Unsigned 128x64 division. Returns 1 if overflow (divide by zero or */
+/* quotient exceeds 64 bits). Otherwise returns quotient via plow and */
+/* remainder via phigh. */
+int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
+{
+ uint64_t dhi = *phigh;
+ uint64_t dlo = *plow;
+ unsigned i;
+ uint64_t carry = 0;
+
+ if (divisor == 0) {
+ return 1;
+ } else if (dhi == 0) {
+ *plow = dlo / divisor;
+ *phigh = dlo % divisor;
+ return 0;
+ } else if (dhi > divisor) {
+ return 1;
+ } else {
+
+ for (i = 0; i < 64; i++) {
+ carry = dhi >> 63;
+ dhi = (dhi << 1) | (dlo >> 63);
+ if (carry | dhi >= divisor) {
+ dhi -= divisor;
+ carry = 1;
+ } else {
+ carry = 0;
+ }
+ dlo = (dlo << 1) | carry;
+ }
+
+ *plow = dlo;
+ *phigh = dhi;
+ return 0;
+ }
+}
#endif /* !CONFIG_INT128 */
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 04/18] target-ppc: Add ISA2.06 divde[o] Instructions
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (2 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 03/18] target-ppc: Add ISA2.06 divdeu[o] Instructions Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 05/18] target-ppc: Add ISA 2.06 divwe[u][o] Instructions Tom Musta
` (14 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the Divide Doubleword Extended instructions.
The implementation builds on the unsigned helper provided in
the previous patch.
V2: Updated to use the host-utils 128 bit divide.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
include/qemu/host-utils.h | 14 ++++++++++++++
target-ppc/helper.h | 1 +
target-ppc/int_helper.c | 23 +++++++++++++++++++++++
target-ppc/translate.c | 4 ++++
util/host-utils.c | 37 +++++++++++++++++++++++++++++++++++++
5 files changed, 79 insertions(+), 0 deletions(-)
diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h
index 0ca187d..39fe018 100644
--- a/include/qemu/host-utils.h
+++ b/include/qemu/host-utils.h
@@ -57,10 +57,24 @@ static inline int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
return result > UINT64_MAX;
}
}
+
+static inline int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
+{
+ if (divisor == 0) {
+ return 1;
+ } else {
+ __int128_t dividend = ((__int128_t)*phigh << 64) | *plow;
+ __int128_t result = dividend / divisor;
+ *plow = result;
+ *phigh = dividend % divisor;
+ return (result > INT64_MAX) | (result < INT64_MIN);
+ }
+}
#else
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
+int divs128(int64_t *plow, int64_t *phigh, int64_t divisor);
#endif
/**
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 3eff4df..4359009 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -32,6 +32,7 @@ DEF_HELPER_5(lscbx, tl, env, tl, i32, i32, i32)
#if defined(TARGET_PPC64)
DEF_HELPER_3(mulldo, i64, env, i64, i64)
DEF_HELPER_4(divdeu, i64, env, i64, i64, i32)
+DEF_HELPER_4(divde, i64, env, i64, i64, i32)
#endif
DEF_HELPER_FLAGS_1(cntlzw, TCG_CALL_NO_RWG_SE, tl, tl)
diff --git a/target-ppc/int_helper.c b/target-ppc/int_helper.c
index d6dcac9..9b289e7 100644
--- a/target-ppc/int_helper.c
+++ b/target-ppc/int_helper.c
@@ -65,6 +65,29 @@ uint64_t helper_divdeu(CPUPPCState *env, uint64_t ra, uint64_t rb, uint32_t oe)
return rt;
}
+uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe)
+{
+ int64_t rt = 0;
+ int64_t ra = (int64_t)rau;
+ int64_t rb = (int64_t)rbu;
+ int overflow = divs128(&rt, &ra, rb);
+
+ if (unlikely(overflow)) {
+ rt = 0; /* Undefined */
+ }
+
+ if (oe) {
+
+ if (unlikely(overflow)) {
+ env->so = env->ov = 1;
+ } else {
+ env->ov = 0;
+ }
+ }
+
+ return rt;
+}
+
#endif
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 7a51c6d..b274a15 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -1048,6 +1048,8 @@ static void gen_##name(DisasContext *ctx) \
GEN_DIVDE(divdeu, divdeu, 0);
GEN_DIVDE(divdeuo, divdeu, 1);
+GEN_DIVDE(divde, divde, 0);
+GEN_DIVDE(divdeo, divde, 1);
#endif
@@ -9613,6 +9615,8 @@ GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1),
GEN_HANDLER_E(divdeu, 0x1F, 0x09, 0x0C, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_HANDLER_E(divdeuo, 0x1F, 0x09, 0x1C, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(divde, 0x1F, 0x09, 0x0D, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(divdeo, 0x1F, 0x09, 0x1D, 0x00000000, PPC_NONE, PPC2_ISA206),
#undef GEN_INT_ARITH_MUL_HELPER
#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
diff --git a/util/host-utils.c b/util/host-utils.c
index b6f7a6e..140e25c 100644
--- a/util/host-utils.c
+++ b/util/host-utils.c
@@ -124,4 +124,41 @@ int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
return 0;
}
}
+
+int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
+{
+ int sgn_dvdnd = *phigh < 0;
+ int sgn_divsr = divisor < 0;
+ int overflow = 0;
+
+ if (sgn_dvdnd) {
+ *plow = ~(*plow);
+ *phigh = ~(*phigh);
+ if (*plow == (int64_t)-1) {
+ *plow = 0;
+ (*phigh)++;
+ } else {
+ (*plow)++;
+ }
+ }
+
+ if (sgn_divsr) {
+ divisor = 0 - divisor;
+ }
+
+ overflow = divu128((uint64_t *)plow, (uint64_t *)phigh, (uint64_t)divisor);
+
+ if (sgn_dvdnd ^ sgn_divsr) {
+ *plow = 0 - *plow;
+ }
+
+ if (!overflow) {
+ if ((*plow < 0) ^ (sgn_dvdnd ^ sgn_divsr)) {
+ overflow = 1;
+ }
+ }
+
+ return overflow;
+}
+
#endif /* !CONFIG_INT128 */
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 05/18] target-ppc: Add ISA 2.06 divwe[u][o] Instructions
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (3 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 04/18] target-ppc: Add ISA2.06 divde[o] Instructions Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 06/18] target-ppc: Add ISA2.06 lbarx, lharx Instructions Tom Musta
` (13 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch addes the Signed and Unsigned Divide Word Extended
instructions which were introduced in Power ISA 2.06.
V2: Eliminating extraneous code in the overflow case per comments
from Richard Henderson. Fixed corner case bug in divweu (check
for (RA) >= (RB)).
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/translate.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index b274a15..3344fa9 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -984,6 +984,72 @@ GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
/* divw divw. divwo divwo. */
GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
+
+#define GEN_DIVWE(op, signed, compute_ov) \
+static void gen_##op(DisasContext *ctx) \
+{ \
+ /* Need to use local temps because of the branches */ \
+ TCGv ra = tcg_temp_local_new(); \
+ TCGv rb = tcg_temp_local_new(); \
+ int lbl_ov = gen_new_label(); \
+ int lbl_rc = gen_new_label(); \
+ \
+ if (signed) { \
+ TCGv tmp0; \
+ /* divide by zero ? */ \
+ tcg_gen_ext32s_i64(rb, cpu_gpr[rB(ctx->opcode)]); \
+ tcg_gen_brcondi_i64(TCG_COND_EQ, rb, 0, lbl_ov); \
+ tcg_gen_shli_i64(ra, cpu_gpr[rA(ctx->opcode)], 32); \
+ /* check for MIN div -1 */ \
+ int l3 = gen_new_label(); \
+ tcg_gen_brcondi_i64(TCG_COND_NE, rb, -1l, l3); \
+ tcg_gen_brcondi_i64(TCG_COND_EQ, ra, INT64_MIN, lbl_ov); \
+ gen_set_label(l3); \
+ tcg_gen_div_i64(cpu_gpr[rD(ctx->opcode)], ra, rb); \
+ tmp0 = tcg_temp_local_new(); \
+ /* does the result fit in 32 bits? */ \
+ tcg_gen_ext32s_i64(tmp0, cpu_gpr[rD(ctx->opcode)]); \
+ tcg_gen_brcond_i64(TCG_COND_NE, cpu_gpr[rD(ctx->opcode)], tmp0, \
+ lbl_ov); \
+ tcg_temp_free(tmp0); \
+ } else { /* unsigned */ \
+ /* divide by zero ? */ \
+ tcg_gen_ext32u_i64(rb, cpu_gpr[rB(ctx->opcode)]); \
+ tcg_gen_brcondi_i64(TCG_COND_EQ, rb, 0, lbl_ov); \
+ /* is ra[32:63] >= rb[32:63] ? */ \
+ tcg_gen_ext32u_i64(ra, cpu_gpr[rA(ctx->opcode)]); \
+ tcg_gen_brcond_i64(TCG_COND_GEU, ra, rb, lbl_ov); \
+ tcg_gen_shli_i64(ra, cpu_gpr[rA(ctx->opcode)], 32); \
+ tcg_gen_divu_i64(cpu_gpr[rD(ctx->opcode)], ra, rb); \
+ } \
+ \
+ if (compute_ov) { \
+ tcg_gen_movi_tl(cpu_ov, 0); \
+ } \
+ tcg_gen_br(lbl_rc); \
+ \
+ gen_set_label(lbl_ov); /* overflow handling */ \
+ tcg_gen_movi_i64(cpu_gpr[rD(ctx->opcode)], 0); \
+ \
+ if (compute_ov) { \
+ tcg_gen_movi_tl(cpu_ov, 1); \
+ tcg_gen_movi_tl(cpu_so, 1); \
+ } \
+ \
+ gen_set_label(lbl_rc); \
+ if (unlikely(Rc(ctx->opcode) != 0)) { \
+ gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); \
+ } \
+ \
+ tcg_temp_free(ra); \
+ tcg_temp_free(rb); \
+}
+
+GEN_DIVWE(divweu, 0, 0);
+GEN_DIVWE(divweuo, 0, 1);
+GEN_DIVWE(divwe, 1, 0);
+GEN_DIVWE(divweo, 1, 1);
+
#if defined(TARGET_PPC64)
static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
TCGv arg2, int sign, int compute_ov)
@@ -9603,6 +9669,10 @@ GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0),
GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1),
GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0),
GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1),
+GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0x00000000, PPC_NONE, PPC2_ISA206),
#if defined(TARGET_PPC64)
#undef GEN_INT_ARITH_DIVD
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 06/18] target-ppc: Add ISA2.06 lbarx, lharx Instructions
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (4 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 05/18] target-ppc: Add ISA 2.06 divwe[u][o] Instructions Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 07/18] target-ppc: Add ISA 2.06 stbcx. and sthcx. Instructions Tom Musta
` (12 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the byte and halfword variations of the Load and
Reserve instructions. Since there is much commonality among
all forms of Load and Reserve, a common macro is provided and the
existing implementations of lwarx and ldarx are re-implemented using
this macro.
V2: Fixed bug in aligment check for lharx (caught by Richard).
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/translate.c | 50 +++++++++++++++++++++++------------------------
1 files changed, 24 insertions(+), 26 deletions(-)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3344fa9..c3d0ebe 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3218,21 +3218,29 @@ static void gen_isync(DisasContext *ctx)
gen_stop_exception(ctx);
}
-/* lwarx */
-static void gen_lwarx(DisasContext *ctx)
-{
- TCGv t0;
- TCGv gpr = cpu_gpr[rD(ctx->opcode)];
- gen_set_access_type(ctx, ACCESS_RES);
- t0 = tcg_temp_local_new();
- gen_addr_reg_index(ctx, t0);
- gen_check_align(ctx, t0, 0x03);
- gen_qemu_ld32u(ctx, gpr, t0);
- tcg_gen_mov_tl(cpu_reserve, t0);
- tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
- tcg_temp_free(t0);
+#define LARX(name, len, loadop) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv t0; \
+ TCGv gpr = cpu_gpr[rD(ctx->opcode)]; \
+ gen_set_access_type(ctx, ACCESS_RES); \
+ t0 = tcg_temp_local_new(); \
+ gen_addr_reg_index(ctx, t0); \
+ if ((len) > 1) { \
+ gen_check_align(ctx, t0, (len)-1); \
+ } \
+ gen_qemu_##loadop(ctx, gpr, t0); \
+ tcg_gen_mov_tl(cpu_reserve, t0); \
+ tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val)); \
+ tcg_temp_free(t0); \
}
+/* lwarx */
+LARX(lbarx, 1, ld8u);
+LARX(lharx, 2, ld16u);
+LARX(lwarx, 4, ld32u);
+
+
#if defined(CONFIG_USER_ONLY)
static void gen_conditional_store (DisasContext *ctx, TCGv EA,
int reg, int size)
@@ -3279,19 +3287,7 @@ static void gen_stwcx_(DisasContext *ctx)
#if defined(TARGET_PPC64)
/* ldarx */
-static void gen_ldarx(DisasContext *ctx)
-{
- TCGv t0;
- TCGv gpr = cpu_gpr[rD(ctx->opcode)];
- gen_set_access_type(ctx, ACCESS_RES);
- t0 = tcg_temp_local_new();
- gen_addr_reg_index(ctx, t0);
- gen_check_align(ctx, t0, 0x07);
- gen_qemu_ld64(ctx, gpr, t0);
- tcg_gen_mov_tl(cpu_reserve, t0);
- tcg_gen_st_tl(gpr, cpu_env, offsetof(CPUPPCState, reserve_val));
- tcg_temp_free(t0);
-}
+LARX(ldarx, 8, ld64);
/* stdcx. */
static void gen_stdcx_(DisasContext *ctx)
@@ -9461,6 +9457,8 @@ GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO),
GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
+GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 07/18] target-ppc: Add ISA 2.06 stbcx. and sthcx. Instructions
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (5 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 06/18] target-ppc: Add ISA2.06 lbarx, lharx Instructions Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 08/18] target-ppc: Add ISA2.06 Float to Integer Instructions Tom Musta
` (11 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the byte and halfword variants of the Store Conditional
instructions. A common macro is introduced and the existing implementations
of stwcx. and stdcx. are re-implemented using this macro.
V2: Re-implemented gen_conditional_store() and STCX macro per comments
from Richard.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/translate.c | 88 ++++++++++++++++++++++-------------------------
1 files changed, 41 insertions(+), 47 deletions(-)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index c3d0ebe..27eef84 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3242,8 +3242,8 @@ LARX(lwarx, 4, ld32u);
#if defined(CONFIG_USER_ONLY)
-static void gen_conditional_store (DisasContext *ctx, TCGv EA,
- int reg, int size)
+static void gen_conditional_store(DisasContext *ctx, TCGv EA,
+ int reg, int size)
{
TCGv t0 = tcg_temp_new();
uint32_t save_exception = ctx->exception;
@@ -3257,62 +3257,54 @@ static void gen_conditional_store (DisasContext *ctx, TCGv EA,
gen_exception(ctx, POWERPC_EXCP_STCX);
ctx->exception = save_exception;
}
-#endif
-
-/* stwcx. */
-static void gen_stwcx_(DisasContext *ctx)
-{
- TCGv t0;
- gen_set_access_type(ctx, ACCESS_RES);
- t0 = tcg_temp_local_new();
- gen_addr_reg_index(ctx, t0);
- gen_check_align(ctx, t0, 0x03);
-#if defined(CONFIG_USER_ONLY)
- gen_conditional_store(ctx, t0, rS(ctx->opcode), 4);
#else
- {
- int l1;
+static void gen_conditional_store(DisasContext *ctx, TCGv EA,
+ int reg, int size)
+{
+ int l1;
- tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
- l1 = gen_new_label();
- tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
- tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
- gen_qemu_st32(ctx, cpu_gpr[rS(ctx->opcode)], t0);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_reserve, -1);
+ tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
+ l1 = gen_new_label();
+ tcg_gen_brcond_tl(TCG_COND_NE, EA, cpu_reserve, l1);
+ tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
+ if (size == 8) {
+ gen_qemu_st64(ctx, cpu_gpr[reg], EA);
+ } else if (size == 4) {
+ gen_qemu_st32(ctx, cpu_gpr[reg], EA);
+ } else if (size == 2) {
+ gen_qemu_st16(ctx, cpu_gpr[reg], EA);
+ } else {
+ gen_qemu_st8(ctx, cpu_gpr[reg], EA);
}
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_reserve, -1);
+}
#endif
- tcg_temp_free(t0);
+
+#define STCX(name, len) \
+static void gen_##name(DisasContext *ctx) \
+{ \
+ TCGv t0; \
+ gen_set_access_type(ctx, ACCESS_RES); \
+ t0 = tcg_temp_local_new(); \
+ gen_addr_reg_index(ctx, t0); \
+ if (len > 1) { \
+ gen_check_align(ctx, t0, (len)-1); \
+ } \
+ gen_conditional_store(ctx, t0, rS(ctx->opcode), len); \
+ tcg_temp_free(t0); \
}
+STCX(stbcx_, 1);
+STCX(sthcx_, 2);
+STCX(stwcx_, 4);
+
#if defined(TARGET_PPC64)
/* ldarx */
LARX(ldarx, 8, ld64);
/* stdcx. */
-static void gen_stdcx_(DisasContext *ctx)
-{
- TCGv t0;
- gen_set_access_type(ctx, ACCESS_RES);
- t0 = tcg_temp_local_new();
- gen_addr_reg_index(ctx, t0);
- gen_check_align(ctx, t0, 0x07);
-#if defined(CONFIG_USER_ONLY)
- gen_conditional_store(ctx, t0, rS(ctx->opcode), 8);
-#else
- {
- int l1;
- tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
- l1 = gen_new_label();
- tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
- tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
- gen_qemu_st64(ctx, cpu_gpr[rS(ctx->opcode)], t0);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_reserve, -1);
- }
-#endif
- tcg_temp_free(t0);
-}
+STCX(stdcx_, 8);
#endif /* defined(TARGET_PPC64) */
/* sync */
@@ -9460,6 +9452,8 @@ GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM),
GEN_HANDLER_E(lbarx, 0x1F, 0x14, 0x01, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_HANDLER_E(lharx, 0x1F, 0x14, 0x03, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000000, PPC_RES),
+GEN_HANDLER_E(stbcx_, 0x1F, 0x16, 0x15, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(sthcx_, 0x1F, 0x16, 0x16, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES),
#if defined(TARGET_PPC64)
GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000000, PPC_64B),
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 08/18] target-ppc: Add ISA2.06 Float to Integer Instructions
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (6 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 07/18] target-ppc: Add ISA 2.06 stbcx. and sthcx. Instructions Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 09/18] softfloat: Fix Handling of Small Negatives in float64_to_uint64 Tom Musta
` (10 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the four floating point to integer conversion instructions
introduced by Power ISA V2.06:
- Floating Convert to Integer Word Unsigned (fctiwu)
- Floating Convert to Integer Word Unsigned with Round Toward
Zero (fctiwuz)
- Floating Convert to Integer Doubleword Unsigned (fctidu)
- Floating Convert to Integer Doubleword Unsigned with Round
Toward Zero (fctiduz)
A common macro is developed to eliminate repetitive code. Existing instructions
are also re-implemented to use this macro (fctiw, fctiwz, fctid, fctidz), thus
eliminating copy/paste code.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/fpu_helper.c | 122 +++++++++++++----------------------------------
target-ppc/helper.h | 4 ++
target-ppc/translate.c | 12 +++++
3 files changed, 50 insertions(+), 88 deletions(-)
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 5d35d1c..17e99c3 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -600,55 +600,41 @@ uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
return farg1.ll;
}
-/* fctiw - fctiw. */
-uint64_t helper_fctiw(CPUPPCState *env, uint64_t arg)
-{
- CPU_DoubleU farg;
-
- farg.ll = arg;
-
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN conversion */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
- POWERPC_EXCP_FP_VXCVI, 1);
- } else if (unlikely(float64_is_quiet_nan(farg.d) ||
- float64_is_infinity(farg.d))) {
- /* qNan / infinity conversion */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
- } else {
- farg.ll = float64_to_int32(farg.d, &env->fp_status);
- /* XXX: higher bits are not supposed to be significant.
- * to make tests easier, return the same as a real PowerPC 750
- */
- farg.ll |= 0xFFF80000ULL << 32;
- }
- return farg.ll;
-}
-
-/* fctiwz - fctiwz. */
-uint64_t helper_fctiwz(CPUPPCState *env, uint64_t arg)
-{
- CPU_DoubleU farg;
- farg.ll = arg;
+#define FPU_FCTI(op, cvt, nanval) \
+uint64_t helper_##op(CPUPPCState *env, uint64_t arg) \
+{ \
+ CPU_DoubleU farg; \
+ \
+ farg.ll = arg; \
+ farg.ll = float64_to_##cvt(farg.d, &env->fp_status); \
+ \
+ if (unlikely(env->fp_status.float_exception_flags)) { \
+ if (float64_is_any_nan(arg)) { \
+ fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1); \
+ if (float64_is_signaling_nan(arg)) { \
+ fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); \
+ } \
+ farg.ll = nanval; \
+ } else if (env->fp_status.float_exception_flags & \
+ float_flag_invalid) { \
+ fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1); \
+ } \
+ helper_float_check_status(env); \
+ } \
+ return farg.ll; \
+ }
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN conversion */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
- POWERPC_EXCP_FP_VXCVI, 1);
- } else if (unlikely(float64_is_quiet_nan(farg.d) ||
- float64_is_infinity(farg.d))) {
- /* qNan / infinity conversion */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
- } else {
- farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
- /* XXX: higher bits are not supposed to be significant.
- * to make tests easier, return the same as a real PowerPC 750
- */
- farg.ll |= 0xFFF80000ULL << 32;
- }
- return farg.ll;
-}
+FPU_FCTI(fctiw, int32, 0x80000000)
+FPU_FCTI(fctiwz, int32_round_to_zero, 0x80000000)
+FPU_FCTI(fctiwu, uint32, 0x00000000)
+FPU_FCTI(fctiwuz, uint32_round_to_zero, 0x00000000)
+#if defined(TARGET_PPC64)
+FPU_FCTI(fctid, int64, 0x8000000000000000)
+FPU_FCTI(fctidz, int64_round_to_zero, 0x8000000000000000)
+FPU_FCTI(fctidu, uint64, 0x0000000000000000)
+FPU_FCTI(fctiduz, uint64_round_to_zero, 0x0000000000000000)
+#endif
#if defined(TARGET_PPC64)
/* fcfid - fcfid. */
@@ -660,47 +646,7 @@ uint64_t helper_fcfid(CPUPPCState *env, uint64_t arg)
return farg.ll;
}
-/* fctid - fctid. */
-uint64_t helper_fctid(CPUPPCState *env, uint64_t arg)
-{
- CPU_DoubleU farg;
- farg.ll = arg;
-
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN conversion */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
- POWERPC_EXCP_FP_VXCVI, 1);
- } else if (unlikely(float64_is_quiet_nan(farg.d) ||
- float64_is_infinity(farg.d))) {
- /* qNan / infinity conversion */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
- } else {
- farg.ll = float64_to_int64(farg.d, &env->fp_status);
- }
- return farg.ll;
-}
-
-/* fctidz - fctidz. */
-uint64_t helper_fctidz(CPUPPCState *env, uint64_t arg)
-{
- CPU_DoubleU farg;
-
- farg.ll = arg;
-
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN conversion */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
- POWERPC_EXCP_FP_VXCVI, 1);
- } else if (unlikely(float64_is_quiet_nan(farg.d) ||
- float64_is_infinity(farg.d))) {
- /* qNan / infinity conversion */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
- } else {
- farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
- }
- return farg.ll;
-}
#endif
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 4359009..4518da0 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -64,11 +64,15 @@ DEF_HELPER_4(fcmpo, void, env, i64, i64, i32)
DEF_HELPER_4(fcmpu, void, env, i64, i64, i32)
DEF_HELPER_2(fctiw, i64, env, i64)
+DEF_HELPER_2(fctiwu, i64, env, i64)
DEF_HELPER_2(fctiwz, i64, env, i64)
+DEF_HELPER_2(fctiwuz, i64, env, i64)
#if defined(TARGET_PPC64)
DEF_HELPER_2(fcfid, i64, env, i64)
DEF_HELPER_2(fctid, i64, env, i64)
+DEF_HELPER_2(fctidu, i64, env, i64)
DEF_HELPER_2(fctidz, i64, env, i64)
+DEF_HELPER_2(fctiduz, i64, env, i64)
#endif
DEF_HELPER_2(frsp, i64, env, i64)
DEF_HELPER_2(frin, i64, env, i64)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 27eef84..5ac00c6 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2263,8 +2263,12 @@ GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
/*** Floating-Point round & convert ***/
/* fctiw */
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
+/* fctiwu */
+GEN_FLOAT_B(ctiwu, 0x0E, 0x04, 0, PPC2_ISA206);
/* fctiwz */
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
+/* fctiwuz */
+GEN_FLOAT_B(ctiwuz, 0x0F, 0x04, 0, PPC2_ISA206);
/* frsp */
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
#if defined(TARGET_PPC64)
@@ -2272,8 +2276,12 @@ GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
/* fctid */
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
+/* fctidu */
+GEN_FLOAT_B(ctidu, 0x0E, 0x1D, 0, PPC2_ISA206);
/* fctidz */
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
+/* fctidu */
+GEN_FLOAT_B(ctiduz, 0x0F, 0x1D, 0, PPC2_ISA206);
#endif
/* frin */
@@ -9788,12 +9796,16 @@ GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
+GEN_HANDLER_E(fctiwu, 0x3F, 0x0E, 0x04, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
+GEN_HANDLER_E(fctiwuz, 0x3F, 0x0F, 0x04, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
#if defined(TARGET_PPC64)
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B),
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B),
+GEN_HANDLER_E(fctidu, 0x3F, 0x0E, 0x1D, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B),
+GEN_HANDLER_E(fctiduz, 0x3F, 0x0F, 0x1D, 0x00000000, PPC_NONE, PPC2_ISA206),
#endif
GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT),
GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 09/18] softfloat: Fix Handling of Small Negatives in float64_to_uint64
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (7 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 08/18] target-ppc: Add ISA2.06 Float to Integer Instructions Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 10/18] softfloat: Fix float64_to_uint64_round_to_zero Tom Musta
` (9 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
The float64_to_uint64 routine exits early for all negative numbers.
While the integer result is always correctly returned as 0, the
exception flags are also always set to float_flag_invalid. This
is incorrect for those cases where a small negative number (-1 < x < 0)
rounds to zero. In such a case, the flag should be reported as
inexact.
The following patch allows these small numbers to flow through the
rounding and packing code.
Some interesting test patterns are:
(1) BC6AEEBA7F390215 / -0x1.aeeba7f390215p-57, round to nearest
even should round up to zero (inexact)
(2) A66A44F252C9AAAC /-0x1.a44f252c9aaacp-409 round up should round
up to zero (inexact)
(3) B4692F3AFFAF2716 / -0x1.92f3affaf2716p-185 round down should
be invalid.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
fpu/softfloat.c | 41 +++++++++++++++++++++--------------------
1 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index cb03dca..3d7a8ff 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -161,7 +161,6 @@ static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM)
| exception is raised and the largest positive or negative integer is
| returned.
*----------------------------------------------------------------------------*/
-
static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATUS_PARAM)
{
int8 roundingMode;
@@ -213,20 +212,24 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATU
| exception is raised and the largest unsigned integer is returned.
*----------------------------------------------------------------------------*/
-static int64 roundAndPackUint64(uint64_t absZ0, uint64_t absZ1 STATUS_PARAM)
+static int64 roundAndPackUint64(flag zSign, uint64_t absZ0,
+ uint64_t absZ1 STATUS_PARAM)
{
int8 roundingMode;
flag roundNearestEven, increment;
- int64_t z;
roundingMode = STATUS(float_rounding_mode);
roundNearestEven = (roundingMode == float_round_nearest_even);
- increment = ((int64_t) absZ1 < 0);
+ increment = ((int64_t)absZ1 < 0);
if (!roundNearestEven) {
if (roundingMode == float_round_to_zero) {
increment = 0;
- } else {
- increment = (roundingMode == float_round_up) && absZ1;
+ } else if (absZ1) {
+ if (zSign) {
+ increment = (roundingMode == float_round_down) && absZ1;
+ } else {
+ increment = (roundingMode == float_round_up) && absZ1;
+ }
}
}
if (increment) {
@@ -237,11 +240,16 @@ static int64 roundAndPackUint64(uint64_t absZ0, uint64_t absZ1 STATUS_PARAM)
}
absZ0 &= ~(((uint64_t)(absZ1<<1) == 0) & roundNearestEven);
}
- z = absZ0;
+
+ if (zSign && absZ0) {
+ float_raise(float_flag_invalid STATUS_VAR);
+ return 0;
+ }
+
if (absZ1) {
STATUS(float_exception_flags) |= float_flag_inexact;
}
- return z;
+ return absZ0;
}
/*----------------------------------------------------------------------------
@@ -1590,7 +1598,7 @@ uint64 float32_to_uint64(float32 a STATUS_PARAM)
aSig64 = aSig;
aSig64 <<= 40;
shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra);
- return roundAndPackUint64(aSig64, aSigExtra STATUS_VAR);
+ return roundAndPackUint64(aSign, aSig64, aSigExtra STATUS_VAR);
}
/*----------------------------------------------------------------------------
@@ -6643,12 +6651,8 @@ uint64_t float64_to_uint64(float64 a STATUS_PARAM)
aSig = extractFloat64Frac(a);
aExp = extractFloat64Exp(a);
aSign = extractFloat64Sign(a);
- if (aSign) {
- if (aExp) {
- float_raise(float_flag_invalid STATUS_VAR);
- } else if (aSig) { /* negative denormalized */
- float_raise(float_flag_inexact STATUS_VAR);
- }
+ if (aSign && (aExp > 1022)) {
+ float_raise(float_flag_invalid STATUS_VAR);
return 0;
}
if (aExp) {
@@ -6657,10 +6661,7 @@ uint64_t float64_to_uint64(float64 a STATUS_PARAM)
shiftCount = 0x433 - aExp;
if (shiftCount <= 0) {
if (0x43E < aExp) {
- if ((aSig != LIT64(0x0010000000000000)) ||
- (aExp == 0x7FF)) {
- float_raise(float_flag_invalid STATUS_VAR);
- }
+ float_raise(float_flag_invalid STATUS_VAR);
return LIT64(0xFFFFFFFFFFFFFFFF);
}
aSigExtra = 0;
@@ -6668,7 +6669,7 @@ uint64_t float64_to_uint64(float64 a STATUS_PARAM)
} else {
shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra);
}
- return roundAndPackUint64(aSig, aSigExtra STATUS_VAR);
+ return roundAndPackUint64(aSign, aSig, aSigExtra STATUS_VAR);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 10/18] softfloat: Fix float64_to_uint64_round_to_zero
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (8 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 09/18] softfloat: Fix Handling of Small Negatives in float64_to_uint64 Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32 Tom Musta
` (8 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
The float64_to_uint64_round_to_zero routine is incorrect.
For example, the following test pattern:
46697351FF4AEC29 / 0x1.97351ff4aec29p+103
currently produces 8000000000000000 instead of FFFFFFFFFFFFFFFF.
This patch re-implements the routine to temporarily force the
rounding mode and use the float64_to_uint64 routine.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
fpu/softfloat.c | 12 +++++-------
1 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 3d7a8ff..1003e59 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6675,13 +6675,11 @@ uint64_t float64_to_uint64(float64 a STATUS_PARAM)
uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
{
- int64_t v;
-
- v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR));
- v += float64_val(a);
- v = float64_to_int64_round_to_zero(make_float64(v) STATUS_VAR);
-
- return v - INT64_MIN;
+ signed char current_rounding_mode = STATUS(float_rounding_mode);
+ set_float_rounding_mode(float_round_to_zero STATUS_VAR);
+ int64_t v = float64_to_uint64(a STATUS_VAR);
+ set_float_rounding_mode(current_rounding_mode STATUS_VAR);
+ return v;
}
#define COMPARE(s, nan_exp) \
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (9 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 10/18] softfloat: Fix float64_to_uint64_round_to_zero Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:53 ` Peter Maydell
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 12/18] softfloat: Fix float64_to_uint32_round_to_zero Tom Musta
` (7 subsequent siblings)
18 siblings, 1 reply; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
The float64_to_uint32 has several flaws:
- for numbers between 2**32 and 2**64, the inexact exception flag
may get incorrectly set. In this case, only the invalid flag
should be set.
test pattern: 425F81378DC0CD1F / 0x1.f81378dc0cd1fp+38
- for numbers between 2**63 and 2**64, incorrect results may
be produced:
test pattern: 43EAAF73F1F0B8BD / 0x1.aaf73f1f0b8bdp+63
This patch re-implements float64_to_uint32 to re-use the
float64_to_uint64 routine (instead of float64_to_int64). For the
saturation case, the inexact bit is explicitly cleared before raising
the invalid flag.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
fpu/softfloat.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 1003e59..6a8b6f5 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6578,15 +6578,13 @@ uint_fast16_t float32_to_uint16_round_to_zero(float32 a STATUS_PARAM)
uint32 float64_to_uint32( float64 a STATUS_PARAM )
{
- int64_t v;
+ uint64_t v;
uint32 res;
- v = float64_to_int64(a STATUS_VAR);
- if (v < 0) {
- res = 0;
- float_raise( float_flag_invalid STATUS_VAR);
- } else if (v > 0xffffffff) {
+ v = float64_to_uint64(a STATUS_VAR);
+ if (v > 0xffffffff) {
res = 0xffffffff;
+ STATUS(float_exception_flags) &= ~float_flag_inexact;
float_raise( float_flag_invalid STATUS_VAR);
} else {
res = v;
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32 Tom Musta
@ 2013-12-11 19:53 ` Peter Maydell
2013-12-11 20:39 ` Tom Musta
0 siblings, 1 reply; 31+ messages in thread
From: Peter Maydell @ 2013-12-11 19:53 UTC (permalink / raw)
To: Tom Musta; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 11 December 2013 19:16, Tom Musta <tommusta@gmail.com> wrote:
> uint32 float64_to_uint32( float64 a STATUS_PARAM )
> {
> - int64_t v;
> + uint64_t v;
> uint32 res;
>
> - v = float64_to_int64(a STATUS_VAR);
> - if (v < 0) {
> - res = 0;
> - float_raise( float_flag_invalid STATUS_VAR);
> - } else if (v > 0xffffffff) {
> + v = float64_to_uint64(a STATUS_VAR);
> + if (v > 0xffffffff) {
> res = 0xffffffff;
> + STATUS(float_exception_flags) &= ~float_flag_inexact;
The IEEE exception flags are cumulative (ie never get cleared
except by guest program explicit request); this change means
that if a previous operation raised the inexact flag you've just
lost that.
thanks
-- PMM
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32
2013-12-11 19:53 ` Peter Maydell
@ 2013-12-11 20:39 ` Tom Musta
2013-12-17 17:45 ` Peter Maydell
0 siblings, 1 reply; 31+ messages in thread
From: Tom Musta @ 2013-12-11 20:39 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 12/11/2013 1:53 PM, Peter Maydell wrote:
> On 11 December 2013 19:16, Tom Musta <tommusta@gmail.com> wrote:
>> uint32 float64_to_uint32( float64 a STATUS_PARAM )
>> {
>> - int64_t v;
>> + uint64_t v;
>> uint32 res;
>>
>> - v = float64_to_int64(a STATUS_VAR);
>> - if (v < 0) {
>> - res = 0;
>> - float_raise( float_flag_invalid STATUS_VAR);
>> - } else if (v > 0xffffffff) {
>> + v = float64_to_uint64(a STATUS_VAR);
>> + if (v > 0xffffffff) {
>> res = 0xffffffff;
>> + STATUS(float_exception_flags) &= ~float_flag_inexact;
>
> The IEEE exception flags are cumulative (ie never get cleared
> except by guest program explicit request); this change means
> that if a previous operation raised the inexact flag you've just
> lost that.
>
> thanks
> -- PMM
>
Thank you, Peter. I will fix.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32
2013-12-11 20:39 ` Tom Musta
@ 2013-12-17 17:45 ` Peter Maydell
2013-12-17 19:32 ` Peter Maydell
2013-12-18 17:32 ` Tom Musta
0 siblings, 2 replies; 31+ messages in thread
From: Peter Maydell @ 2013-12-17 17:45 UTC (permalink / raw)
To: Tom Musta; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 11 December 2013 20:39, Tom Musta <tommusta@gmail.com> wrote:
> On 12/11/2013 1:53 PM, Peter Maydell wrote:
>> On 11 December 2013 19:16, Tom Musta <tommusta@gmail.com> wrote:
>>> uint32 float64_to_uint32( float64 a STATUS_PARAM )
>>> {
>>> - int64_t v;
>>> + uint64_t v;
>>> uint32 res;
>>>
>>> - v = float64_to_int64(a STATUS_VAR);
>>> - if (v < 0) {
>>> - res = 0;
>>> - float_raise( float_flag_invalid STATUS_VAR);
>>> - } else if (v > 0xffffffff) {
>>> + v = float64_to_uint64(a STATUS_VAR);
>>> + if (v > 0xffffffff) {
>>> res = 0xffffffff;
>>> + STATUS(float_exception_flags) &= ~float_flag_inexact;
>>
>> The IEEE exception flags are cumulative (ie never get cleared
>> except by guest program explicit request); this change means
>> that if a previous operation raised the inexact flag you've just
>> lost that.
>>
>> thanks
>> -- PMM
>>
> Thank you, Peter. I will fix.
I'm partway through fixing this bug in an implementation of
float*_to_uint16 which the ARM AArch64 needs. I think the
cleanest approach to this looks like this:
uint32 float64_to_uint32( float64 a STATUS_PARAM )
{
int64_t v;
uint32 res;
int old_exc_flags = get_float_exception_flags(status);
v = float64_to_uint64(a STATUS_VAR);
if (v > 0xffffffff) {
res = 0xffffffff;
} else {
return v;
}
set_float_exception_flags(old_exc_flags);
float_raise(float_flag_invalid STATUS_VAR);
return res;
}
thanks
-- PMM
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32
2013-12-17 17:45 ` Peter Maydell
@ 2013-12-17 19:32 ` Peter Maydell
2013-12-18 17:32 ` Tom Musta
1 sibling, 0 replies; 31+ messages in thread
From: Peter Maydell @ 2013-12-17 19:32 UTC (permalink / raw)
To: Tom Musta; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 17 December 2013 17:45, Peter Maydell <peter.maydell@linaro.org> wrote:
> I'm partway through fixing this bug in an implementation of
> float*_to_uint16 which the ARM AArch64 needs. I think the
> cleanest approach to this looks like this:
>
> uint32 float64_to_uint32( float64 a STATUS_PARAM )
> {
> int64_t v;
> uint32 res;
> int old_exc_flags = get_float_exception_flags(status);
>
> v = float64_to_uint64(a STATUS_VAR);
> if (v > 0xffffffff) {
> res = 0xffffffff;
> } else {
> return v;
> }
> set_float_exception_flags(old_exc_flags);
...should be
set_float_exception_flags(old_exc_flags, status);
> float_raise(float_flag_invalid STATUS_VAR);
> return res;
> }
thanks
-- PMM
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32
2013-12-17 17:45 ` Peter Maydell
2013-12-17 19:32 ` Peter Maydell
@ 2013-12-18 17:32 ` Tom Musta
2013-12-18 18:03 ` Peter Maydell
1 sibling, 1 reply; 31+ messages in thread
From: Tom Musta @ 2013-12-18 17:32 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 12/17/2013 11:45 AM, Peter Maydell wrote:
> On 11 December 2013 20:39, Tom Musta <tommusta@gmail.com> wrote:
>> On 12/11/2013 1:53 PM, Peter Maydell wrote:
>>> On 11 December 2013 19:16, Tom Musta <tommusta@gmail.com> wrote:
>>>> uint32 float64_to_uint32( float64 a STATUS_PARAM )
>>>> {
>>>> - int64_t v;
>>>> + uint64_t v;
>>>> uint32 res;
>>>>
>>>> - v = float64_to_int64(a STATUS_VAR);
>>>> - if (v < 0) {
>>>> - res = 0;
>>>> - float_raise( float_flag_invalid STATUS_VAR);
>>>> - } else if (v > 0xffffffff) {
>>>> + v = float64_to_uint64(a STATUS_VAR);
>>>> + if (v > 0xffffffff) {
>>>> res = 0xffffffff;
>>>> + STATUS(float_exception_flags) &= ~float_flag_inexact;
>>>
>>> The IEEE exception flags are cumulative (ie never get cleared
>>> except by guest program explicit request); this change means
>>> that if a previous operation raised the inexact flag you've just
>>> lost that.
>>>
>>> thanks
>>> -- PMM
>>>
>> Thank you, Peter. I will fix.
>
> I'm partway through fixing this bug in an implementation of
> float*_to_uint16 which the ARM AArch64 needs. I think the
> cleanest approach to this looks like this:
>
> uint32 float64_to_uint32( float64 a STATUS_PARAM )
> {
> int64_t v;
> uint32 res;
> int old_exc_flags = get_float_exception_flags(status);
>
> v = float64_to_uint64(a STATUS_VAR);
> if (v > 0xffffffff) {
> res = 0xffffffff;
> } else {
> return v;
> }
> set_float_exception_flags(old_exc_flags);
> float_raise(float_flag_invalid STATUS_VAR);
> return res;
> }
>
> thanks
> -- PMM
>
This seems to assume that the only case where flags could be set in
float64_to_uint32 is the case where a large result is returned. Is
this really the case?
I was thinking something like this:
uint32 float64_to_uint32( float64 a STATUS_PARAM )
{
uint64_t v;
uint32 res;
int inexact = (STATUS(float_exception_flags) & float_flag_inexact) != 0;
v = float64_to_uint64(a STATUS_VAR);
if (v > 0xffffffff) {
res = 0xffffffff;
/* If the inexact flag was set during this operation, then clear it. */
if (!inexact) {
STATUS(float_exception_flags) &= ~float_flag_inexact;
}
float_raise( float_flag_invalid STATUS_VAR);
} else {
res = v;
}
return res;
}
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32
2013-12-18 17:32 ` Tom Musta
@ 2013-12-18 18:03 ` Peter Maydell
2013-12-18 18:23 ` Tom Musta
0 siblings, 1 reply; 31+ messages in thread
From: Peter Maydell @ 2013-12-18 18:03 UTC (permalink / raw)
To: Tom Musta; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 18 December 2013 17:32, Tom Musta <tommusta@gmail.com> wrote:
> On 12/17/2013 11:45 AM, Peter Maydell wrote:
>> I'm partway through fixing this bug in an implementation of
>> float*_to_uint16 which the ARM AArch64 needs. I think the
>> cleanest approach to this looks like this:
>>
>> uint32 float64_to_uint32( float64 a STATUS_PARAM )
>> {
>> int64_t v;
>> uint32 res;
>> int old_exc_flags = get_float_exception_flags(status);
>>
>> v = float64_to_uint64(a STATUS_VAR);
>> if (v > 0xffffffff) {
>> res = 0xffffffff;
>> } else {
>> return v;
>> }
>> set_float_exception_flags(old_exc_flags);
>> float_raise(float_flag_invalid STATUS_VAR);
>> return res;
>> }
>>
>> thanks
>> -- PMM
>>
>
> This seems to assume that the only case where flags could be set in
> float64_to_uint32 is the case where a large result is returned. Is
> this really the case?
No, all it's assuming is that if we have the out-of-range
case then the only flag that should be set is Invalid.
In the "result is correct" case we return v and don't
modify the flags from what float64_to_uint64() has set.
Do you think there are flags that should be allowed
to be set by the conversion operation even if it is signaling
Invalid because of out of range input? IEEE754-2008 section 7.1
says "An invocation of [any operation except directly modifying
the flags] might raise at most two status flags, overflow
with inexact or underflow with inexact". That is, any operation
might (1) raise no flags (2) raise just one flag (3) raise
Overflow+Inexact (4) raise Underflow+Inexact.
[QEMU/softfloat don't suport alternate exception handling
so we can ignore the standard's verbiage about that.]
There is also the softfloat-specific float_flag_input_denormal,
but I think that is also fine because it will only be set by the
operation if we're squashing input denormals to zero, in
which case the float-to-int conversion must always successfully
return zero (because we squashed the input to plus or minus
zero).
This is a bit complicated though, so maybe I missed a case?
thanks
-- PMM
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32
2013-12-18 18:03 ` Peter Maydell
@ 2013-12-18 18:23 ` Tom Musta
0 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-18 18:23 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 12/18/2013 12:03 PM, Peter Maydell wrote:
> On 18 December 2013 17:32, Tom Musta <tommusta@gmail.com> wrote:
>> On 12/17/2013 11:45 AM, Peter Maydell wrote:
>>
>> This seems to assume that the only case where flags could be set in
>> float64_to_uint32 is the case where a large result is returned. Is
>> this really the case?
>
> No, all it's assuming is that if we have the out-of-range
> case then the only flag that should be set is Invalid.
> In the "result is correct" case we return v and don't
> modify the flags from what float64_to_uint64() has set.
>
> Do you think there are flags that should be allowed
> to be set by the conversion operation even if it is signaling
> Invalid because of out of range input? IEEE754-2008 section 7.1
> says "An invocation of [any operation except directly modifying
> the flags] might raise at most two status flags, overflow
> with inexact or underflow with inexact". That is, any operation
> might (1) raise no flags (2) raise just one flag (3) raise
> Overflow+Inexact (4) raise Underflow+Inexact.
> [QEMU/softfloat don't suport alternate exception handling
> so we can ignore the standard's verbiage about that.]
>
> There is also the softfloat-specific float_flag_input_denormal,
> but I think that is also fine because it will only be set by the
> operation if we're squashing input denormals to zero, in
> which case the float-to-int conversion must always successfully
> return zero (because we squashed the input to plus or minus
> zero).
>
> This is a bit complicated though, so maybe I missed a case?
>
> thanks
> -- PMM
>
I'm sorry Peter ... I misread your patch. I see what you are doing
now.
I'll use your pattern, retest and resubmit.
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 12/18] softfloat: Fix float64_to_uint32_round_to_zero
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (10 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 11/18] softfloat: Fix float64_to_uint32 Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:54 ` Peter Maydell
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 13/18] target-ppc: Add ISA 2.06 fcfid[u][s] Instructions Tom Musta
` (6 subsequent siblings)
18 siblings, 1 reply; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
The float64_to_uint32_round_to_zero routine is incorrect.
For example, the following test pattern:
425F81378DC0CD1F / 0x1.f81378dc0cd1fp+38
will erroneously set the inexact flag.
This patch re-implements the routine to temporarily force the
rounding mode and use the float64_to_uint32 routine.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
fpu/softfloat.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6a8b6f5..052c202 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6594,15 +6594,13 @@ uint32 float64_to_uint32( float64 a STATUS_PARAM )
uint32 float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
{
- int64_t v;
+ uint64_t v;
uint32 res;
- v = float64_to_int64_round_to_zero(a STATUS_VAR);
- if (v < 0) {
- res = 0;
- float_raise( float_flag_invalid STATUS_VAR);
- } else if (v > 0xffffffff) {
+ v = float64_to_uint64_round_to_zero(a STATUS_VAR);
+ if (v > 0xffffffff) {
res = 0xffffffff;
+ STATUS(float_exception_flags) &= ~float_flag_inexact;
float_raise( float_flag_invalid STATUS_VAR);
} else {
res = v;
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 12/18] softfloat: Fix float64_to_uint32_round_to_zero
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 12/18] softfloat: Fix float64_to_uint32_round_to_zero Tom Musta
@ 2013-12-11 19:54 ` Peter Maydell
0 siblings, 0 replies; 31+ messages in thread
From: Peter Maydell @ 2013-12-11 19:54 UTC (permalink / raw)
To: Tom Musta; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 11 December 2013 19:16, Tom Musta <tommusta@gmail.com> wrote:
> The float64_to_uint32_round_to_zero routine is incorrect.
>
> For example, the following test pattern:
>
> 425F81378DC0CD1F / 0x1.f81378dc0cd1fp+38
>
> will erroneously set the inexact flag.
>
> This patch re-implements the routine to temporarily force the
> rounding mode and use the float64_to_uint32 routine.
> uint32 float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
> {
> - int64_t v;
> + uint64_t v;
> uint32 res;
>
> - v = float64_to_int64_round_to_zero(a STATUS_VAR);
> - if (v < 0) {
> - res = 0;
> - float_raise( float_flag_invalid STATUS_VAR);
> - } else if (v > 0xffffffff) {
> + v = float64_to_uint64_round_to_zero(a STATUS_VAR);
> + if (v > 0xffffffff) {
> res = 0xffffffff;
> + STATUS(float_exception_flags) &= ~float_flag_inexact;
> float_raise( float_flag_invalid STATUS_VAR);
> } else {
> res = v;
The patch doesn't seem to be doing what the commit message
says it does?
thanks
-- PMM
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 13/18] target-ppc: Add ISA 2.06 fcfid[u][s] Instructions
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (11 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 12/18] softfloat: Fix float64_to_uint32_round_to_zero Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 14/18] target-ppc: Fix and enable fri[mnpz] Tom Musta
` (5 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the fcfids, fcfidu and fcfidus instructions which
were introduced in Power ISA 2.06. A common macro is provided to
eliminated redudant code, and the existing fcfid instruction is
re-implemented to use this macro.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/fpu_helper.c | 23 ++++++++++++++++-------
target-ppc/helper.h | 3 +++
target-ppc/translate.c | 9 +++++++++
3 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 17e99c3..18b9bcd 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -637,16 +637,25 @@ FPU_FCTI(fctiduz, uint64_round_to_zero, 0x0000000000000000)
#endif
#if defined(TARGET_PPC64)
-/* fcfid - fcfid. */
-uint64_t helper_fcfid(CPUPPCState *env, uint64_t arg)
-{
- CPU_DoubleU farg;
-
- farg.d = int64_to_float64(arg, &env->fp_status);
- return farg.ll;
-}
-
+#define FPU_FCFI(op, cvtr, is_single) \
+uint64_t helper_##op(CPUPPCState *env, uint64_t arg) \
+{ \
+ CPU_DoubleU farg; \
+ \
+ farg.d = cvtr(arg, &env->fp_status); \
+ \
+ if (is_single) { \
+ farg.d = helper_frsp(env, farg.d); \
+ } \
+ helper_float_check_status(env); \
+ return farg.ll; \
+}
+
+FPU_FCFI(fcfid, int64_to_float64, 0)
+FPU_FCFI(fcfids, int64_to_float64, 1)
+FPU_FCFI(fcfidu, uint64_to_float64, 0)
+FPU_FCFI(fcfidus, uint64_to_float64, 1)
#endif
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 4518da0..19b2f6b 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -69,6 +69,9 @@ DEF_HELPER_2(fctiwz, i64, env, i64)
DEF_HELPER_2(fctiwuz, i64, env, i64)
#if defined(TARGET_PPC64)
DEF_HELPER_2(fcfid, i64, env, i64)
+DEF_HELPER_2(fcfidu, i64, env, i64)
+DEF_HELPER_2(fcfids, i64, env, i64)
+DEF_HELPER_2(fcfidus, i64, env, i64)
DEF_HELPER_2(fctid, i64, env, i64)
DEF_HELPER_2(fctidu, i64, env, i64)
DEF_HELPER_2(fctidz, i64, env, i64)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 5ac00c6..9f0c682 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2274,6 +2274,12 @@ GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
#if defined(TARGET_PPC64)
/* fcfid */
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
+/* fcfids */
+GEN_FLOAT_B(cfids, 0x0E, 0x1A, 0, PPC2_ISA206);
+/* fcfidu */
+GEN_FLOAT_B(cfidu, 0x0E, 0x1E, 0, PPC2_ISA206);
+/* fcfidus */
+GEN_FLOAT_B(cfidus, 0x0E, 0x1E, 0, PPC2_ISA206);
/* fctid */
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
/* fctidu */
@@ -9802,6 +9808,9 @@ GEN_HANDLER_E(fctiwuz, 0x3F, 0x0F, 0x04, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT),
#if defined(TARGET_PPC64)
GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B),
+GEN_HANDLER_E(fcfids, 0x3B, 0x0E, 0x1A, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(fcfidu, 0x3F, 0x0E, 0x1E, 0x00000000, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(fcfidus, 0x3B, 0x0E, 0x1E, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B),
GEN_HANDLER_E(fctidu, 0x3F, 0x0E, 0x1D, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B),
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 14/18] target-ppc: Fix and enable fri[mnpz]
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (12 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 13/18] target-ppc: Add ISA 2.06 fcfid[u][s] Instructions Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 15/18] target-ppc: Add ISA 2.06 ftdiv Instruction Tom Musta
` (4 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
The fri* series of instructions was introduced prior to ISA 2.06 and
is supported on Power7 and Power8 hardware. However, the instruction
is still considered illegal in the P7 and P8 QEMU emulation models.
This patch enables these instructions for the P7 and P8 machines.
Also, the existing helper is modified to correctly handle some of
the boundary cases (NaNs and the inexact flag).
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/fpu_helper.c | 12 ++++++------
target-ppc/translate_init.c | 2 ++
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 18b9bcd..981f002 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -668,18 +668,18 @@ static inline uint64_t do_fri(CPUPPCState *env, uint64_t arg,
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN round */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
- POWERPC_EXCP_FP_VXCVI, 1);
- } else if (unlikely(float64_is_quiet_nan(farg.d) ||
- float64_is_infinity(farg.d))) {
- /* qNan / infinity round */
- farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);
+ fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ farg.ll = float64_default_nan | 0x0008000000000000ul;
} else {
set_float_rounding_mode(rounding_mode, &env->fp_status);
farg.ll = float64_round_to_int(farg.d, &env->fp_status);
/* Restore rounding mode from FPSCR */
fpscr_set_rounding_mode(env);
+
+ /* fri* does not set FPSCR[XX] */
+ env->fp_status.float_exception_flags &= ~float_flag_inexact;
}
+ helper_float_check_status(env);
return farg.ll;
}
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 491e56c..7bb9bbc 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7228,6 +7228,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
PPC_FLOAT_STFIWX |
+ PPC_FLOAT_EXT |
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
@@ -7265,6 +7266,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
PPC_FLOAT_STFIWX |
+ PPC_FLOAT_EXT |
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 15/18] target-ppc: Add ISA 2.06 ftdiv Instruction
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (13 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 14/18] target-ppc: Fix and enable fri[mnpz] Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 16/18] target-ppc: Add ISA 2.06 ftsqrt Tom Musta
` (3 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the Floating Point Test for Divide instruction which
was introduced in Power ISA 2.06.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/fpu_helper.c | 56 ++++++++++++++++++++++++++++++++++++++--------
target-ppc/helper.h | 2 +
target-ppc/translate.c | 17 ++++++++++++++
3 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 981f002..82ff0db 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -50,6 +50,16 @@ static inline int isden(float64 d)
return ((u.ll >> 52) & 0x7FF) == 0;
}
+static inline int ppc_float32_get_unbiased_exp(float32 f)
+{
+ return ((f >> 23) & 0xFF) - 127;
+}
+
+static inline int ppc_float64_get_unbiased_exp(float64 f)
+{
+ return ((f >> 52) & 0x7FF) - 1023;
+}
+
uint32_t helper_compute_fprf(CPUPPCState *env, uint64_t arg, uint32_t set_fprf)
{
CPU_DoubleU farg;
@@ -988,6 +998,42 @@ uint64_t helper_fsel(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
}
}
+void helper_ftdiv(CPUPPCState *env, uint32_t bf, uint64_t fra, uint64_t frb)
+{
+ int fe_flag = 0;
+ int fg_flag = 0;
+
+ if (unlikely(float64_is_infinity(fra) ||
+ float64_is_infinity(frb) ||
+ float64_is_zero(frb))) {
+ fe_flag = 1;
+ fg_flag = 1;
+ } else {
+ int e_a = ppc_float64_get_unbiased_exp(fra);
+ int e_b = ppc_float64_get_unbiased_exp(frb);
+
+ if (unlikely(float64_is_any_nan(fra) ||
+ float64_is_any_nan(frb))) {
+ fe_flag = 1;
+ } else if ((e_b <= -1022) || (e_b >= 1021)) {
+ fe_flag = 1;
+ } else if (!float64_is_zero(fra) &&
+ (((e_a - e_b) >= 1023) ||
+ ((e_a - e_b) <= -1021) ||
+ (e_a <= -970))) {
+ fe_flag = 1;
+ }
+
+ if (unlikely(float64_is_zero_or_denormal(frb))) {
+ /* XB is not zero because of the above check and */
+ /* so must be denormalized. */
+ fg_flag = 1;
+ }
+ }
+
+ env->crf[bf] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0);
+}
+
void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
uint32_t crfD)
{
@@ -2016,16 +2062,6 @@ VSX_RSQRTE(xsrsqrtesp, 1, float64, f64, 1, 1)
VSX_RSQRTE(xvrsqrtedp, 2, float64, f64, 0, 0)
VSX_RSQRTE(xvrsqrtesp, 4, float32, f32, 0, 0)
-static inline int ppc_float32_get_unbiased_exp(float32 f)
-{
- return ((f >> 23) & 0xFF) - 127;
-}
-
-static inline int ppc_float64_get_unbiased_exp(float64 f)
-{
- return ((f >> 52) & 0x7FF) - 1023;
-}
-
/* VSX_TDIV - VSX floating point test for divide
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 19b2f6b..5f5d3f6 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -97,6 +97,8 @@ DEF_HELPER_2(fres, i64, env, i64)
DEF_HELPER_2(frsqrte, i64, env, i64)
DEF_HELPER_4(fsel, i64, env, i64, i64, i64)
+DEF_HELPER_4(ftdiv, void, env, i32, i64, i64)
+
#define dh_alias_avr ptr
#define dh_ctype_avr ppc_avr_t *
#define dh_is_signed_avr dh_is_signed_ptr
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 9f0c682..403e274 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2299,6 +2299,22 @@ GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
/* frim */
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
+static void gen_ftdiv(DisasContext *ctx)
+{
+ TCGv_i32 bf;
+ if (unlikely(!ctx->fpu_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_FPU);
+ return;
+ }
+ /* NIP cannot be restored if the memory exception comes from an helper */
+ gen_update_nip(ctx, ctx->nip - 4);
+ bf = tcg_const_i32(crfD(ctx->opcode));
+ gen_helper_ftdiv(cpu_env, bf, cpu_fpr[rA(ctx->opcode)],
+ cpu_fpr[rB(ctx->opcode)]);
+}
+
+
+
/*** Floating-Point compare ***/
/* fcmpo */
@@ -9801,6 +9817,7 @@ GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
+GEN_HANDLER_E(ftdiv, 0x3F, 0x00, 0x04, 1, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
GEN_HANDLER_E(fctiwu, 0x3F, 0x0E, 0x04, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 16/18] target-ppc: Add ISA 2.06 ftsqrt
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (14 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 15/18] target-ppc: Add ISA 2.06 ftdiv Instruction Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 17/18] target-ppc: Enable frsqrtes on Power7 and Power8 Tom Musta
` (2 subsequent siblings)
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the Floating Point Test for Square Root instruction
which was introduced in Power ISA 2.06.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/fpu_helper.c | 31 +++++++++++++++++++++++++++++++
target-ppc/helper.h | 1 +
target-ppc/translate.c | 14 ++++++++++++++
3 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 82ff0db..d5eb4ef 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -1034,6 +1034,37 @@ void helper_ftdiv(CPUPPCState *env, uint32_t bf, uint64_t fra, uint64_t frb)
env->crf[bf] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0);
}
+void helper_ftsqrt(CPUPPCState *env, uint32_t bf, uint64_t frb)
+{
+ int fe_flag = 0;
+ int fg_flag = 0;
+
+ if (unlikely(float64_is_infinity(frb) || float64_is_zero(frb))) {
+ fe_flag = 1;
+ fg_flag = 1;
+ } else {
+ int e_b = ppc_float64_get_unbiased_exp(frb);
+
+ if (unlikely(float64_is_any_nan(frb))) {
+ fe_flag = 1;
+ } else if (unlikely(float64_is_zero(frb))) {
+ fe_flag = 1;
+ } else if (unlikely(float64_is_neg(frb))) {
+ fe_flag = 1;
+ } else if (!float64_is_zero(frb) && (e_b <= (-1022+52))) {
+ fe_flag = 1;
+ }
+
+ if (unlikely(float64_is_zero_or_denormal(frb))) {
+ /* XB is not zero because of the above check and */
+ /* therefore must be denormalized. */
+ fg_flag = 1;
+ }
+ }
+
+ env->crf[bf] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0);
+}
+
void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
uint32_t crfD)
{
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 5f5d3f6..ccf5711 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -98,6 +98,7 @@ DEF_HELPER_2(frsqrte, i64, env, i64)
DEF_HELPER_4(fsel, i64, env, i64, i64, i64)
DEF_HELPER_4(ftdiv, void, env, i32, i64, i64)
+DEF_HELPER_3(ftsqrt, void, env, i32, i64)
#define dh_alias_avr ptr
#define dh_ctype_avr ppc_avr_t *
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 403e274..0833606 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2313,6 +2313,19 @@ static void gen_ftdiv(DisasContext *ctx)
cpu_fpr[rB(ctx->opcode)]);
}
+static void gen_ftsqrt(DisasContext *ctx)
+{
+ TCGv_i32 bf;
+ if (unlikely(!ctx->fpu_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_FPU);
+ return;
+ }
+ /* NIP cannot be restored if the memory exception comes from an helper */
+ gen_update_nip(ctx, ctx->nip - 4);
+ bf = tcg_const_i32(crfD(ctx->opcode));
+ gen_helper_ftsqrt(cpu_env, bf, cpu_fpr[rB(ctx->opcode)]);
+}
+
/*** Floating-Point compare ***/
@@ -9818,6 +9831,7 @@ GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT),
GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT),
GEN_HANDLER_E(ftdiv, 0x3F, 0x00, 0x04, 1, PPC_NONE, PPC2_ISA206),
+GEN_HANDLER_E(ftsqrt, 0x3F, 0x00, 0x05, 1, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT),
GEN_HANDLER_E(fctiwu, 0x3F, 0x0E, 0x04, 0x00000000, PPC_NONE, PPC2_ISA206),
GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT),
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 17/18] target-ppc: Enable frsqrtes on Power7 and Power8
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (15 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 16/18] target-ppc: Add ISA 2.06 ftsqrt Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 18/18] target-ppc: Add ISA2.06 lfiwzx Instruction Tom Musta
2013-12-11 19:40 ` [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Peter Maydell
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
The frsqrtes instruction was introduced prior to ISA 2.06 and is
support on both the Power7 and Power8 processors. However, this
instruction is handled as illegal in the current QEMU emulation
machines. This patch enables the existing implemention of frsqrtes
in the P7 and P8 machines.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/translate_init.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 7bb9bbc..ec65bf4 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7227,6 +7227,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
+ PPC_FLOAT_FRSQRTES |
PPC_FLOAT_STFIWX |
PPC_FLOAT_EXT |
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
@@ -7265,6 +7266,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
+ PPC_FLOAT_FRSQRTES |
PPC_FLOAT_STFIWX |
PPC_FLOAT_EXT |
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [V2 PATCH 18/18] target-ppc: Add ISA2.06 lfiwzx Instruction
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (16 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 17/18] target-ppc: Enable frsqrtes on Power7 and Power8 Tom Musta
@ 2013-12-11 19:16 ` Tom Musta
2013-12-11 19:40 ` [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Peter Maydell
18 siblings, 0 replies; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:16 UTC (permalink / raw)
To: qemu-devel; +Cc: Tom Musta, qemu-ppc
This patch adds the Load Floating Point as Integer Word and
Zero Indexed (lfiwzx) instruction which was introduced in
Power ISA 2.06.
Signed-off-by: Tom Musta <tommusta@gmail.com>
---
target-ppc/translate.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 0833606..cf1fb1b 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3524,6 +3524,20 @@ static void gen_lfiwax(DisasContext *ctx)
tcg_temp_free(t0);
}
+/* lfiwzx */
+static void gen_lfiwzx(DisasContext *ctx)
+{
+ TCGv EA;
+ if (unlikely(!ctx->fpu_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_FPU);
+ return;
+ }
+ gen_set_access_type(ctx, ACCESS_FLOAT);
+ EA = tcg_temp_new();
+ gen_addr_reg_index(ctx, EA);
+ gen_qemu_ld32u(ctx, cpu_fpr[rD(ctx->opcode)], EA);
+ tcg_temp_free(EA);
+}
/*** Floating-point store ***/
#define GEN_STF(name, stop, opc, type) \
static void glue(gen_, name)(DisasContext *ctx) \
@@ -9937,6 +9951,7 @@ GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
+GEN_HANDLER_E(lfiwzx, 0x1f, 0x17, 0x1b, 0x00000001, PPC_NONE, PPC2_ISA206),
GEN_HANDLER_E(lfdp, 0x39, 0xFF, 0xFF, 0x00200003, PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205),
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8
2013-12-11 19:16 [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Tom Musta
` (17 preceding siblings ...)
2013-12-11 19:16 ` [Qemu-devel] [V2 PATCH 18/18] target-ppc: Add ISA2.06 lfiwzx Instruction Tom Musta
@ 2013-12-11 19:40 ` Peter Maydell
2013-12-11 19:42 ` Tom Musta
18 siblings, 1 reply; 31+ messages in thread
From: Peter Maydell @ 2013-12-11 19:40 UTC (permalink / raw)
To: Tom Musta; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 11 December 2013 19:16, Tom Musta <tommusta@gmail.com> wrote:
> Additionally, some bugs in the common floating point library (softfloat)
> are fixed.
> fpu/softfloat.c | 73 +++++------
All patches which touch fpu/ need to come with a statement
(in the cover letter is fine) that the changes are licensed under
both the softfloat-2a and -2b licenses [or under some license
compatible with both, I guess]. (We're trying to relicense that
area of the codebase at the moment.)
thanks
-- PMM
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8
2013-12-11 19:40 ` [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8 Peter Maydell
@ 2013-12-11 19:42 ` Tom Musta
2013-12-11 19:50 ` Peter Maydell
0 siblings, 1 reply; 31+ messages in thread
From: Tom Musta @ 2013-12-11 19:42 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 12/11/2013 1:40 PM, Peter Maydell wrote:
> On 11 December 2013 19:16, Tom Musta <tommusta@gmail.com> wrote:
>> Additionally, some bugs in the common floating point library (softfloat)
>> are fixed.
>
>> fpu/softfloat.c | 73 +++++------
>
> All patches which touch fpu/ need to come with a statement
> (in the cover letter is fine) that the changes are licensed under
> both the softfloat-2a and -2b licenses [or under some license
> compatible with both, I guess]. (We're trying to relicense that
> area of the codebase at the moment.)
>
> thanks
> -- PMM
>
Arrrrghhh!!!! I should have remembered that. Sucks that this stuff
can't be consistent with the rest of the code.
V3 forthcoming.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [V2 PATCH 00/18] target-ppc: Base ISA V2.06 for Power7/Power8
2013-12-11 19:42 ` Tom Musta
@ 2013-12-11 19:50 ` Peter Maydell
0 siblings, 0 replies; 31+ messages in thread
From: Peter Maydell @ 2013-12-11 19:50 UTC (permalink / raw)
To: Tom Musta; +Cc: qemu-ppc@nongnu.org, QEMU Developers
On 11 December 2013 19:42, Tom Musta <tommusta@gmail.com> wrote:
> On 12/11/2013 1:40 PM, Peter Maydell wrote:
>> All patches which touch fpu/ need to come with a statement
>> (in the cover letter is fine) that the changes are licensed under
>> both the softfloat-2a and -2b licenses [or under some license
>> compatible with both, I guess]. (We're trying to relicense that
>> area of the codebase at the moment.)
>
> Arrrrghhh!!!! I should have remembered that. Sucks that this stuff
> can't be consistent with the rest of the code.
A reply here will do, you don't need to respin just for this.
thanks
-- PMM
^ permalink raw reply [flat|nested] 31+ messages in thread