Convert the following opcodes to decodetree:
- MULT.G - multiply 32-bit signed integers
- MULTU.G - multiply 32-bit unsigned integers
- DMULT.G - multiply 64-bit signed integers
- DMULTU.G - multiply 64-bit unsigned integers
Now that all opcodes from the extension have been converted, we
can remove completely gen_loongson_integer() and its 2 calls in
decode_opc_special2_legacy() and decode_opc_special3_legacy().
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
target/mips/godson2.decode | 5 ++
target/mips/loong-ext.decode | 5 ++
target/mips/loong_translate.c | 58 ++++++++++++++++++++++
target/mips/translate.c | 92 +----------------------------------
4 files changed, 70 insertions(+), 90 deletions(-)
diff --git a/target/mips/godson2.decode b/target/mips/godson2.decode
index 805452fa975..cf12d9072ec 100644
--- a/target/mips/godson2.decode
+++ b/target/mips/godson2.decode
@@ -13,6 +13,11 @@
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+MULT.G 011111 ..... ..... ..... 00000 011000 @rs_rt_rd
+MULTU.G 011111 ..... ..... ..... 00000 011001 @rs_rt_rd
+DMULT.G 011111 ..... ..... ..... 00000 011100 @rs_rt_rd
+DMULTU.G 011111 ..... ..... ..... 00000 011101 @rs_rt_rd
+
DIV.G 011111 ..... ..... ..... 00000 011010 @rs_rt_rd
DIVU.G 011111 ..... ..... ..... 00000 011011 @rs_rt_rd
DDIV.G 011111 ..... ..... ..... 00000 011110 @rs_rt_rd
diff --git a/target/mips/loong-ext.decode b/target/mips/loong-ext.decode
index b0715894ee1..2281afaad95 100644
--- a/target/mips/loong-ext.decode
+++ b/target/mips/loong-ext.decode
@@ -14,6 +14,11 @@
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+MULT.G 011100 ..... ..... ..... 00000 010000 @rs_rt_rd
+DMULT.G 011100 ..... ..... ..... 00000 010001 @rs_rt_rd
+MULTU.G 011100 ..... ..... ..... 00000 010010 @rs_rt_rd
+DMULTU.G 011100 ..... ..... ..... 00000 010011 @rs_rt_rd
+
DIV.G 011100 ..... ..... ..... 00000 010100 @rs_rt_rd
DDIV.G 011100 ..... ..... ..... 00000 010101 @rs_rt_rd
DIVU.G 011100 ..... ..... ..... 00000 010110 @rs_rt_rd
diff --git a/target/mips/loong_translate.c b/target/mips/loong_translate.c
index 50609ce4178..2af94535921 100644
--- a/target/mips/loong_translate.c
+++ b/target/mips/loong_translate.c
@@ -263,6 +263,64 @@ static bool trans_DMODU_G(DisasContext *s, arg_muldiv *a)
return gen_lext_MODU_G(s, a->rt, a->rs, a->rd, true);
}
+static bool gen_lext_MULT_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double, bool is_unsigned)
+{
+ TCGv t0, t1;
+
+ if (is_double) {
+ if (TARGET_LONG_BITS != 64) {
+ return false;
+ }
+ check_mips_64(s);
+ }
+
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return true;
+ }
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ if (is_unsigned && !is_double) {
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ }
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+
+ return true;
+}
+
+static bool trans_MULT_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, false);
+}
+
+static bool trans_MULTU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, true);
+}
+
+static bool trans_DMULT_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, false);
+}
+
+static bool trans_DMULTU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, true);
+}
+
bool decode_loongson(DisasContext *ctx, uint32_t insn)
{
if ((ctx->insn_flags & INSN_LOONGSON2E)
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 144e51b063a..5b5fe31c534 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -337,11 +337,6 @@ enum {
OPC_MUL = 0x02 | OPC_SPECIAL2,
OPC_MSUB = 0x04 | OPC_SPECIAL2,
OPC_MSUBU = 0x05 | OPC_SPECIAL2,
- /* Loongson 2F */
- OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
- OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
- OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
- OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
/* Misc */
OPC_CLZ = 0x20 | OPC_SPECIAL2,
OPC_CLO = 0x21 | OPC_SPECIAL2,
@@ -370,12 +365,6 @@ enum {
OPC_RDHWR = 0x3B | OPC_SPECIAL3,
OPC_GINV = 0x3D | OPC_SPECIAL3,
- /* Loongson 2E */
- OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
- OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
- OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
- OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
-
/* MIPS DSP Load */
OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
/* MIPS DSP Arithmetic */
@@ -4962,65 +4951,6 @@ static void gen_cl(DisasContext *ctx, uint32_t opc,
}
}
-/* Godson integer instructions */
-static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
- int rd, int rs, int rt)
-{
- TCGv t0, t1;
-
- if (rd == 0) {
- /* Treat as NOP. */
- return;
- }
-
- switch (opc) {
- case OPC_MULT_G_2E:
- case OPC_MULT_G_2F:
- case OPC_MULTU_G_2E:
- case OPC_MULTU_G_2F:
-#if defined(TARGET_MIPS64)
- case OPC_DMULT_G_2E:
- case OPC_DMULT_G_2F:
- case OPC_DMULTU_G_2E:
- case OPC_DMULTU_G_2F:
-#endif
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
- break;
- }
-
- gen_load_gpr(t0, rs);
- gen_load_gpr(t1, rt);
-
- switch (opc) {
- case OPC_MULT_G_2E:
- case OPC_MULT_G_2F:
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- break;
- case OPC_MULTU_G_2E:
- case OPC_MULTU_G_2F:
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- break;
-#if defined(TARGET_MIPS64)
- case OPC_DMULT_G_2E:
- case OPC_DMULT_G_2F:
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- break;
- case OPC_DMULTU_G_2E:
- case OPC_DMULTU_G_2F:
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- break;
-#endif
- }
-
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-}
-
/* Loongson multimedia instructions */
static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
{
@@ -26989,11 +26919,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
case OPC_MUL:
gen_arith(ctx, op1, rd, rs, rt);
break;
- case OPC_MULT_G_2F:
- case OPC_MULTU_G_2F:
- check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- break;
case OPC_CLO:
case OPC_CLZ:
check_insn(ctx, ISA_MIPS_R1);
@@ -27018,11 +26943,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
check_mips_64(ctx);
gen_cl(ctx, op1, rd, rs);
break;
- case OPC_DMULT_G_2F:
- case OPC_DMULTU_G_2F:
- check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- break;
#endif
default: /* Invalid */
MIPS_INVAL("special2_legacy");
@@ -27155,10 +27075,9 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
- case OPC_MULT_G_2E:
- case OPC_MULTU_G_2E:
+ case OPC_MUL_PH_DSP:
/*
- * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
+ * OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
* the same mask and op1.
*/
if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MUL_PH_DSP)) {
@@ -27189,8 +27108,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
gen_reserved_instruction(ctx);
break;
}
- } else if (ctx->insn_flags & INSN_LOONGSON2E) {
- gen_loongson_integer(ctx, op1, rd, rs, rt);
} else {
gen_reserved_instruction(ctx);
}
@@ -27422,11 +27339,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
}
break;
#if defined(TARGET_MIPS64)
- case OPC_DMULT_G_2E:
- case OPC_DMULTU_G_2E:
- check_insn(ctx, INSN_LOONGSON2E);
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- break;
case OPC_ABSQ_S_QH_DSP:
op2 = MASK_ABSQ_S_QH(ctx->opcode);
switch (op2) {
--
2.26.2
On 1/12/21 11:55 AM, Philippe Mathieu-Daudé wrote:
> Convert the following opcodes to decodetree:
>
> - MULT.G - multiply 32-bit signed integers
> - MULTU.G - multiply 32-bit unsigned integers
> - DMULT.G - multiply 64-bit signed integers
> - DMULTU.G - multiply 64-bit unsigned integers
>
> Now that all opcodes from the extension have been converted, we
> can remove completely gen_loongson_integer() and its 2 calls in
> decode_opc_special2_legacy() and decode_opc_special3_legacy().
>
> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> ---
> target/mips/godson2.decode | 5 ++
> target/mips/loong-ext.decode | 5 ++
> target/mips/loong_translate.c | 58 ++++++++++++++++++++++
> target/mips/translate.c | 92 +----------------------------------
> 4 files changed, 70 insertions(+), 90 deletions(-)
>
> diff --git a/target/mips/godson2.decode b/target/mips/godson2.decode
> index 805452fa975..cf12d9072ec 100644
> --- a/target/mips/godson2.decode
> +++ b/target/mips/godson2.decode
> @@ -13,6 +13,11 @@
>
> @rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
>
> +MULT.G 011111 ..... ..... ..... 00000 011000 @rs_rt_rd
> +MULTU.G 011111 ..... ..... ..... 00000 011001 @rs_rt_rd
> +DMULT.G 011111 ..... ..... ..... 00000 011100 @rs_rt_rd
> +DMULTU.G 011111 ..... ..... ..... 00000 011101 @rs_rt_rd
> +
> DIV.G 011111 ..... ..... ..... 00000 011010 @rs_rt_rd
> DIVU.G 011111 ..... ..... ..... 00000 011011 @rs_rt_rd
> DDIV.G 011111 ..... ..... ..... 00000 011110 @rs_rt_rd
> diff --git a/target/mips/loong-ext.decode b/target/mips/loong-ext.decode
> index b0715894ee1..2281afaad95 100644
> --- a/target/mips/loong-ext.decode
> +++ b/target/mips/loong-ext.decode
> @@ -14,6 +14,11 @@
>
> @rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
>
> +MULT.G 011100 ..... ..... ..... 00000 010000 @rs_rt_rd
> +DMULT.G 011100 ..... ..... ..... 00000 010001 @rs_rt_rd
> +MULTU.G 011100 ..... ..... ..... 00000 010010 @rs_rt_rd
> +DMULTU.G 011100 ..... ..... ..... 00000 010011 @rs_rt_rd
> +
> DIV.G 011100 ..... ..... ..... 00000 010100 @rs_rt_rd
> DDIV.G 011100 ..... ..... ..... 00000 010101 @rs_rt_rd
> DIVU.G 011100 ..... ..... ..... 00000 010110 @rs_rt_rd
> diff --git a/target/mips/loong_translate.c b/target/mips/loong_translate.c
> index 50609ce4178..2af94535921 100644
> --- a/target/mips/loong_translate.c
> +++ b/target/mips/loong_translate.c
> @@ -263,6 +263,64 @@ static bool trans_DMODU_G(DisasContext *s, arg_muldiv *a)
> return gen_lext_MODU_G(s, a->rt, a->rs, a->rd, true);
> }
>
> +static bool gen_lext_MULT_G(DisasContext *s, int rd, int rs, int rt,
> + bool is_double, bool is_unsigned)
> +{
> + TCGv t0, t1;
> +
> + if (is_double) {
> + if (TARGET_LONG_BITS != 64) {
> + return false;
> + }
> + check_mips_64(s);
> + }
> +
> + if (rd == 0) {
> + /* Treat as NOP. */
> + return true;
> + }
> +
> + t0 = tcg_temp_new();
> + t1 = tcg_temp_new();
> +
> + gen_load_gpr(t0, rs);
> + gen_load_gpr(t1, rt);
> +
> + if (is_unsigned && !is_double) {
> + tcg_gen_ext32u_tl(t0, t0);
> + tcg_gen_ext32u_tl(t1, t1);
> + }
While this is a faithful conversion of the existing code, these extensions make
no difference to the result. They are redundant with
> + tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
> + if (!is_double) {
> + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
this one, which discards any bit that might have been set by the input bits
that are cleared.
There is no actual difference between MULT.G and MULTU.G, or DMULT.G and
DMULTU.G, because they don't record the most significant bits of the infinite
result in any way.
> +static bool trans_MULT_G(DisasContext *s, arg_muldiv *a)
> +{
> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, false);
> +}
> +
> +static bool trans_MULTU_G(DisasContext *s, arg_muldiv *a)
> +{
> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, true);
> +}
> +
> +static bool trans_DMULT_G(DisasContext *s, arg_muldiv *a)
> +{
> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, false);
> +}
> +
> +static bool trans_DMULTU_G(DisasContext *s, arg_muldiv *a)
> +{
> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, true);
> +}
So... if you want to clean this up afterward, or before is up to you.
r~
On 21/1/21 21:06, Richard Henderson wrote:
> On 1/12/21 11:55 AM, Philippe Mathieu-Daudé wrote:
>> Convert the following opcodes to decodetree:
>>
>> - MULT.G - multiply 32-bit signed integers
>> - MULTU.G - multiply 32-bit unsigned integers
>> - DMULT.G - multiply 64-bit signed integers
>> - DMULTU.G - multiply 64-bit unsigned integers
>>
>> Now that all opcodes from the extension have been converted, we
>> can remove completely gen_loongson_integer() and its 2 calls in
>> decode_opc_special2_legacy() and decode_opc_special3_legacy().
>>
>> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>> ---
>> target/mips/godson2.decode | 5 ++
>> target/mips/loong-ext.decode | 5 ++
>> target/mips/loong_translate.c | 58 ++++++++++++++++++++++
>> target/mips/translate.c | 92 +----------------------------------
>> 4 files changed, 70 insertions(+), 90 deletions(-)
>>
>> diff --git a/target/mips/godson2.decode b/target/mips/godson2.decode
>> index 805452fa975..cf12d9072ec 100644
>> --- a/target/mips/godson2.decode
>> +++ b/target/mips/godson2.decode
>> @@ -13,6 +13,11 @@
>>
>> @rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
>>
>> +MULT.G 011111 ..... ..... ..... 00000 011000 @rs_rt_rd
>> +MULTU.G 011111 ..... ..... ..... 00000 011001 @rs_rt_rd
>> +DMULT.G 011111 ..... ..... ..... 00000 011100 @rs_rt_rd
>> +DMULTU.G 011111 ..... ..... ..... 00000 011101 @rs_rt_rd
>> +
>> DIV.G 011111 ..... ..... ..... 00000 011010 @rs_rt_rd
>> DIVU.G 011111 ..... ..... ..... 00000 011011 @rs_rt_rd
>> DDIV.G 011111 ..... ..... ..... 00000 011110 @rs_rt_rd
>> diff --git a/target/mips/loong-ext.decode b/target/mips/loong-ext.decode
>> index b0715894ee1..2281afaad95 100644
>> --- a/target/mips/loong-ext.decode
>> +++ b/target/mips/loong-ext.decode
>> @@ -14,6 +14,11 @@
>>
>> @rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
>>
>> +MULT.G 011100 ..... ..... ..... 00000 010000 @rs_rt_rd
>> +DMULT.G 011100 ..... ..... ..... 00000 010001 @rs_rt_rd
>> +MULTU.G 011100 ..... ..... ..... 00000 010010 @rs_rt_rd
>> +DMULTU.G 011100 ..... ..... ..... 00000 010011 @rs_rt_rd
>> +
>> DIV.G 011100 ..... ..... ..... 00000 010100 @rs_rt_rd
>> DDIV.G 011100 ..... ..... ..... 00000 010101 @rs_rt_rd
>> DIVU.G 011100 ..... ..... ..... 00000 010110 @rs_rt_rd
>> diff --git a/target/mips/loong_translate.c b/target/mips/loong_translate.c
>> index 50609ce4178..2af94535921 100644
>> --- a/target/mips/loong_translate.c
>> +++ b/target/mips/loong_translate.c
>> @@ -263,6 +263,64 @@ static bool trans_DMODU_G(DisasContext *s, arg_muldiv *a)
>> return gen_lext_MODU_G(s, a->rt, a->rs, a->rd, true);
>> }
>>
>> +static bool gen_lext_MULT_G(DisasContext *s, int rd, int rs, int rt,
>> + bool is_double, bool is_unsigned)
>> +{
>> + TCGv t0, t1;
>> +
>> + if (is_double) {
>> + if (TARGET_LONG_BITS != 64) {
>> + return false;
>> + }
>> + check_mips_64(s);
>> + }
>> +
>> + if (rd == 0) {
>> + /* Treat as NOP. */
>> + return true;
>> + }
>> +
>> + t0 = tcg_temp_new();
>> + t1 = tcg_temp_new();
>> +
>> + gen_load_gpr(t0, rs);
>> + gen_load_gpr(t1, rt);
>> +
>> + if (is_unsigned && !is_double) {
>> + tcg_gen_ext32u_tl(t0, t0);
>> + tcg_gen_ext32u_tl(t1, t1);
>> + }
>
> While this is a faithful conversion of the existing code, these extensions make
> no difference to the result. They are redundant with
>
>> + tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
>> + if (!is_double) {
>> + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
>
> this one, which discards any bit that might have been set by the input bits
> that are cleared.
I see.
> There is no actual difference between MULT.G and MULTU.G, or DMULT.G and
> DMULTU.G, because they don't record the most significant bits of the infinite
> result in any way.
Right.
>> +static bool trans_MULT_G(DisasContext *s, arg_muldiv *a)
>> +{
>> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, false);
>> +}
>> +
>> +static bool trans_MULTU_G(DisasContext *s, arg_muldiv *a)
>> +{
>> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, true);
>> +}
>> +
>> +static bool trans_DMULT_G(DisasContext *s, arg_muldiv *a)
>> +{
>> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, false);
>> +}
>> +
>> +static bool trans_DMULTU_G(DisasContext *s, arg_muldiv *a)
>> +{
>> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, true);
>> +}
>
> So... if you want to clean this up afterward, or before is up to you.
IIUC you are suggesting this simplification:
-- >8 --
diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
index 4fb8fdba9c..86015ac8e5 100644
--- a/target/mips/tcg/godson2.decode
+++ b/target/mips/tcg/godson2.decode
@@ -15,6 +15,4 @@
-MULT_G 011111 ..... ..... ..... 00000 011000 @rs_rt_rd
-MULTU_G 011111 ..... ..... ..... 00000 011001 @rs_rt_rd
-DMULT_G 011111 ..... ..... ..... 00000 011100 @rs_rt_rd
-DMULTU_G 011111 ..... ..... ..... 00000 011101 @rs_rt_rd
+MULTu_G 011111 ..... ..... ..... 00000 01100- @rs_rt_rd
+DMULTu_G 011111 ..... ..... ..... 00000 01110- @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode
b/target/mips/tcg/loong-ext.decode
index d2c46d3110..b05236eb41 100644
--- a/target/mips/tcg/loong-ext.decode
+++ b/target/mips/tcg/loong-ext.decode
@@ -16,6 +16,4 @@
-MULT_G 011100 ..... ..... ..... 00000 010000 @rs_rt_rd
-DMULT_G 011100 ..... ..... ..... 00000 010001 @rs_rt_rd
-MULTU_G 011100 ..... ..... ..... 00000 010010 @rs_rt_rd
-DMULTU_G 011100 ..... ..... ..... 00000 010011 @rs_rt_rd
+MULTu_G 011100 ..... ..... ..... 00000 0100-0 @rs_rt_rd
+DMULTu_G 011100 ..... ..... ..... 00000 0100-1 @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c
b/target/mips/tcg/loong_translate.c
index 672d8b6163..4b6bdf28be 100644
--- a/target/mips/tcg/loong_translate.c
+++ b/target/mips/tcg/loong_translate.c
@@ -253,3 +253,3 @@ static bool trans_DMODU_G(DisasContext *s,
arg_muldiv *a)
static bool gen_lext_MULT_G(DisasContext *s, int rd, int rs, int rt,
- bool is_double, bool is_unsigned)
+ bool is_double)
{
@@ -275,6 +275,2 @@ static bool gen_lext_MULT_G(DisasContext *s, int rd,
int rs, int rt,
- if (is_unsigned && !is_double) {
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- }
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
@@ -287,20 +283,10 @@ static bool gen_lext_MULT_G(DisasContext *s, int
rd, int rs, int rt,
-static bool trans_MULT_G(DisasContext *s, arg_muldiv *a)
+static bool trans_MULTu_G(DisasContext *s, arg_muldiv *a)
{
- return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, false);
+ return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false);
}
-static bool trans_MULTU_G(DisasContext *s, arg_muldiv *a)
+static bool trans_DMULTu_G(DisasContext *s, arg_muldiv *a)
{
- return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, true);
-}
-
-static bool trans_DMULT_G(DisasContext *s, arg_muldiv *a)
-{
- return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, false);
-}
-
-static bool trans_DMULTU_G(DisasContext *s, arg_muldiv *a)
-{
- return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, true);
+ return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true);
}
---
Is that correct?
On 31/8/23 21:12, Philippe Mathieu-Daudé wrote:
> On 21/1/21 21:06, Richard Henderson wrote:
>> On 1/12/21 11:55 AM, Philippe Mathieu-Daudé wrote:
>>> Convert the following opcodes to decodetree:
>>>
>>> - MULT.G - multiply 32-bit signed integers
>>> - MULTU.G - multiply 32-bit unsigned integers
>>> - DMULT.G - multiply 64-bit signed integers
>>> - DMULTU.G - multiply 64-bit unsigned integers
>>>
>>> Now that all opcodes from the extension have been converted, we
>>> can remove completely gen_loongson_integer() and its 2 calls in
>>> decode_opc_special2_legacy() and decode_opc_special3_legacy().
>>>
>>> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>> ---
>>> target/mips/godson2.decode | 5 ++
>>> target/mips/loong-ext.decode | 5 ++
>>> target/mips/loong_translate.c | 58 ++++++++++++++++++++++
>>> target/mips/translate.c | 92 +----------------------------------
>>> 4 files changed, 70 insertions(+), 90 deletions(-)
>>> +static bool gen_lext_MULT_G(DisasContext *s, int rd, int rs, int rt,
>>> + bool is_double, bool is_unsigned)
>>> +{
>>> + TCGv t0, t1;
>>> +
>>> + if (is_double) {
>>> + if (TARGET_LONG_BITS != 64) {
>>> + return false;
>>> + }
>>> + check_mips_64(s);
>>> + }
>>> +
>>> + if (rd == 0) {
>>> + /* Treat as NOP. */
>>> + return true;
>>> + }
>>> +
>>> + t0 = tcg_temp_new();
>>> + t1 = tcg_temp_new();
>>> +
>>> + gen_load_gpr(t0, rs);
>>> + gen_load_gpr(t1, rt);
>>> +
>>> + if (is_unsigned && !is_double) {
>>> + tcg_gen_ext32u_tl(t0, t0);
>>> + tcg_gen_ext32u_tl(t1, t1);
>>> + }
>>
>> While this is a faithful conversion of the existing code, these
>> extensions make
>> no difference to the result. They are redundant with
>>
>>> + tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
>>> + if (!is_double) {
>>> + tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
>>
>> this one, which discards any bit that might have been set by the input
>> bits
>> that are cleared.
>
> I see.
>
>> There is no actual difference between MULT.G and MULTU.G, or DMULT.G and
>> DMULTU.G, because they don't record the most significant bits of the
>> infinite
>> result in any way.
>
> Right.
>
>>> +static bool trans_MULT_G(DisasContext *s, arg_muldiv *a)
>>> +{
>>> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, false);
>>> +}
>>> +
>>> +static bool trans_MULTU_G(DisasContext *s, arg_muldiv *a)
>>> +{
>>> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false, true);
>>> +}
>>> +
>>> +static bool trans_DMULT_G(DisasContext *s, arg_muldiv *a)
>>> +{
>>> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, false);
>>> +}
>>> +
>>> +static bool trans_DMULTU_G(DisasContext *s, arg_muldiv *a)
>>> +{
>>> + return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true, true);
>>> +}
>>
>> So... if you want to clean this up afterward, or before is up to you.
"before" ended being way simpler :>
© 2016 - 2026 Red Hat, Inc.