diff mbox

[RFC,5/6] target-ppc: add modulo word operations

Message ID 1468346602-20700-6-git-send-email-nikunj@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Nikunj A. Dadhania July 12, 2016, 6:03 p.m. UTC
Adding following instructions:

moduw: Modulo Unsigned Word
modsw: Modulo Signed Word

Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
 target-ppc/translate.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

Comments

David Gibson July 18, 2016, 2:04 a.m. UTC | #1
On Tue, Jul 12, 2016 at 11:33:21PM +0530, Nikunj A Dadhania wrote:
> Adding following instructions:
> 
> moduw: Modulo Unsigned Word
> modsw: Modulo Signed Word
> 
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>

Hrm.. any reason you're not using the TCG inbuilt remainder ops
(tcg_gen_rem_i32() etc.)?

> ---
>  target-ppc/translate.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
> 
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index 8de217f..c505684 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -1178,6 +1178,54 @@ GEN_DIVE(divde, divde, 0);
>  GEN_DIVE(divdeo, divde, 1);
>  #endif
>  
> +static inline void gen_op_arith_modw(DisasContext *ctx, TCGv ret, TCGv arg1,
> +                                     TCGv arg2, int sign)
> +{
> +    TCGLabel *l1 = gen_new_label();
> +    TCGLabel *l2 = gen_new_label();
> +    TCGv_i32 t0 = tcg_temp_local_new_i32();
> +    TCGv_i32 t1 = tcg_temp_local_new_i32();
> +    TCGv_i32 t2 = tcg_temp_local_new_i32();
> +
> +    tcg_gen_trunc_tl_i32(t0, arg1);
> +    tcg_gen_trunc_tl_i32(t1, arg2);
> +    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
> +    if (sign) {
> +        TCGLabel *l3 = gen_new_label();
> +        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
> +        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
> +        gen_set_label(l3);
> +        tcg_gen_div_i32(t2, t0, t1);
> +    } else {
> +        tcg_gen_divu_i32(t2, t0, t1);
> +    }
> +    tcg_gen_mul_i32(t2, t2, t1);
> +    tcg_gen_sub_i32(t2, t0, t2);
> +    tcg_gen_br(l2);
> +    gen_set_label(l1);
> +    if (sign) {
> +        tcg_gen_sari_i32(t2, t0, 31);
> +    } else {
> +        tcg_gen_movi_i32(t2, 0);
> +    }
> +    gen_set_label(l2);
> +    tcg_gen_extu_i32_tl(ret, t2);
> +    tcg_temp_free_i32(t0);
> +    tcg_temp_free_i32(t1);
> +    tcg_temp_free_i32(t2);
> +}
> +
> +#define GEN_INT_ARITH_MODW(name, opc3, sign)                                \
> +static void glue(gen_, name)(DisasContext *ctx)                             \
> +{                                                                           \
> +    gen_op_arith_modw(ctx, cpu_gpr[rD(ctx->opcode)],                        \
> +                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],   \
> +                      sign);                                                \
> +}
> +
> +GEN_INT_ARITH_MODW(modsw, 0x18, 1);
> +GEN_INT_ARITH_MODW(moduw, 0x08, 0);
> +
>  /* mulhw  mulhw. */
>  static void gen_mulhw(DisasContext *ctx)
>  {
> @@ -10244,6 +10292,8 @@ GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
>  GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
>  GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
>  GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
> +GEN_HANDLER_E(modsw, 0x1F, 0x0B, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300),
> +GEN_HANDLER_E(moduw, 0x1F, 0x0B, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300),
>  
>  #if defined(TARGET_PPC64)
>  #undef GEN_INT_ARITH_DIVD
Nikunj A. Dadhania July 18, 2016, 5:08 a.m. UTC | #2
David Gibson <david@gibson.dropbear.id.au> writes:

> [ Unknown signature status ]
> On Tue, Jul 12, 2016 at 11:33:21PM +0530, Nikunj A Dadhania wrote:
>> Adding following instructions:
>> 
>> moduw: Modulo Unsigned Word
>> modsw: Modulo Signed Word
>> 
>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>
> Hrm.. any reason you're not using the TCG inbuilt remainder ops
> (tcg_gen_rem_i32() etc.)?

I have an updated version with me which uses inbuilt ops, i was searching
for modulo expressions, which I didn't find, so wrote. Found later that
it is called tcg_gen_rem. Will send in the next version.

Regards
Nikunj
Richard Henderson July 21, 2016, 6:24 a.m. UTC | #3
On 07/18/2016 10:38 AM, Nikunj A Dadhania wrote:
> David Gibson <david@gibson.dropbear.id.au> writes:
>
>> [ Unknown signature status ]
>> On Tue, Jul 12, 2016 at 11:33:21PM +0530, Nikunj A Dadhania wrote:
>>> Adding following instructions:
>>>
>>> moduw: Modulo Unsigned Word
>>> modsw: Modulo Signed Word
>>>
>>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>>
>> Hrm.. any reason you're not using the TCG inbuilt remainder ops
>> (tcg_gen_rem_i32() etc.)?
>
> I have an updated version with me which uses inbuilt ops, i was searching
> for modulo expressions, which I didn't find, so wrote. Found later that
> it is called tcg_gen_rem. Will send in the next version.

It would probably be better to use helper functions for both div and mod, 
because of the branches required.

C.f. target-arm/helper-a64.c, helper_sdiv64 et al.


r~
Nikunj A. Dadhania July 21, 2016, 8:11 a.m. UTC | #4
Richard Henderson <rth@twiddle.net> writes:

> On 07/18/2016 10:38 AM, Nikunj A Dadhania wrote:
>> David Gibson <david@gibson.dropbear.id.au> writes:
>>
>>> [ Unknown signature status ]
>>> On Tue, Jul 12, 2016 at 11:33:21PM +0530, Nikunj A Dadhania wrote:
>>>> Adding following instructions:
>>>>
>>>> moduw: Modulo Unsigned Word
>>>> modsw: Modulo Signed Word
>>>>
>>>> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
>>>
>>> Hrm.. any reason you're not using the TCG inbuilt remainder ops
>>> (tcg_gen_rem_i32() etc.)?
>>
>> I have an updated version with me which uses inbuilt ops, i was searching
>> for modulo expressions, which I didn't find, so wrote. Found later that
>> it is called tcg_gen_rem. Will send in the next version.
>
> It would probably be better to use helper functions for both div and mod, 
> because of the branches required.
>
> C.f. target-arm/helper-a64.c, helper_sdiv64 et al.

What is the thumb rule to implement it has helper?
As I am implementing other instructions as well.

One as you suggested many branches.

Regards
Nikunj
Richard Henderson July 21, 2016, 10:24 a.m. UTC | #5
On 07/21/2016 01:41 PM, Nikunj A Dadhania wrote:
>> It would probably be better to use helper functions for both div and mod,
>> because of the branches required.
>>
>> C.f. target-arm/helper-a64.c, helper_sdiv64 et al.
>
> What is the thumb rule to implement it has helper?
> As I am implementing other instructions as well.
>
> One as you suggested many branches.

Branches, or more than, say, 15 tcg instructions.

The former rule is primarily because branches inhibit all tcg optimization.

The latter rule is more flexible, depending on how many of them you expect may 
be able to optimize away.  For ppc, I would expect few dead code opportunities; 
those are more for cisc targets that compute flags with every instruction.


r~
diff mbox

Patch

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 8de217f..c505684 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -1178,6 +1178,54 @@  GEN_DIVE(divde, divde, 0);
 GEN_DIVE(divdeo, divde, 1);
 #endif
 
+static inline void gen_op_arith_modw(DisasContext *ctx, TCGv ret, TCGv arg1,
+                                     TCGv arg2, int sign)
+{
+    TCGLabel *l1 = gen_new_label();
+    TCGLabel *l2 = gen_new_label();
+    TCGv_i32 t0 = tcg_temp_local_new_i32();
+    TCGv_i32 t1 = tcg_temp_local_new_i32();
+    TCGv_i32 t2 = tcg_temp_local_new_i32();
+
+    tcg_gen_trunc_tl_i32(t0, arg1);
+    tcg_gen_trunc_tl_i32(t1, arg2);
+    tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
+    if (sign) {
+        TCGLabel *l3 = gen_new_label();
+        tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
+        tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
+        gen_set_label(l3);
+        tcg_gen_div_i32(t2, t0, t1);
+    } else {
+        tcg_gen_divu_i32(t2, t0, t1);
+    }
+    tcg_gen_mul_i32(t2, t2, t1);
+    tcg_gen_sub_i32(t2, t0, t2);
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    if (sign) {
+        tcg_gen_sari_i32(t2, t0, 31);
+    } else {
+        tcg_gen_movi_i32(t2, 0);
+    }
+    gen_set_label(l2);
+    tcg_gen_extu_i32_tl(ret, t2);
+    tcg_temp_free_i32(t0);
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t2);
+}
+
+#define GEN_INT_ARITH_MODW(name, opc3, sign)                                \
+static void glue(gen_, name)(DisasContext *ctx)                             \
+{                                                                           \
+    gen_op_arith_modw(ctx, cpu_gpr[rD(ctx->opcode)],                        \
+                      cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],   \
+                      sign);                                                \
+}
+
+GEN_INT_ARITH_MODW(modsw, 0x18, 1);
+GEN_INT_ARITH_MODW(moduw, 0x08, 0);
+
 /* mulhw  mulhw. */
 static void gen_mulhw(DisasContext *ctx)
 {
@@ -10244,6 +10292,8 @@  GEN_HANDLER_E(divwe, 0x1F, 0x0B, 0x0D, 0, PPC_NONE, PPC2_DIVE_ISA206),
 GEN_HANDLER_E(divweo, 0x1F, 0x0B, 0x1D, 0, PPC_NONE, PPC2_DIVE_ISA206),
 GEN_HANDLER_E(divweu, 0x1F, 0x0B, 0x0C, 0, PPC_NONE, PPC2_DIVE_ISA206),
 GEN_HANDLER_E(divweuo, 0x1F, 0x0B, 0x1C, 0, PPC_NONE, PPC2_DIVE_ISA206),
+GEN_HANDLER_E(modsw, 0x1F, 0x0B, 0x18, 0x00000001, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(moduw, 0x1F, 0x0B, 0x08, 0x00000001, PPC_NONE, PPC2_ISA300),
 
 #if defined(TARGET_PPC64)
 #undef GEN_INT_ARITH_DIVD