[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [V3 PATCH 03/14] target-ppc: Add ISA2.06 divdeu[o] Instru
From: |
Scott Wood |
Subject: |
Re: [Qemu-ppc] [V3 PATCH 03/14] target-ppc: Add ISA2.06 divdeu[o] Instructions |
Date: |
Fri, 27 Dec 2013 18:30:26 -0600 |
On Wed, 2013-12-18 at 14:48 -0600, Tom Musta wrote:
> 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 <address@hidden>
> ---
> 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),
These instructions are phased-in on embedded, and unlike bpermd are not
present on e5500/e6500 which are 64-bit ISA 2.06 implementations.
Wasn't the conclusion in a previous thread to use separate flags for
these instruction groups?
-Scott
Re: [Qemu-ppc] [Qemu-devel] [V3 PATCH 02/14] target-ppc: Add ISA2.06 bpermd Instruction, Scott Wood, 2013/12/27
[Qemu-ppc] [V3 PATCH 04/14] target-ppc: Add ISA2.06 divde[o] Instructions, Tom Musta, 2013/12/18
[Qemu-ppc] [V3 PATCH 01/14] target-ppc: Add Flag for Power ISA V2.06, Tom Musta, 2013/12/18