* [PATCH v2 1/7] target/mips: Simplify Loongson MULTU.G opcode
2023-08-31 20:30 [PATCH v2 0/7] target/mips: Convert Loongson LEXT opcodes to decodetree Philippe Mathieu-Daudé
@ 2023-08-31 20:30 ` Philippe Mathieu-Daudé
2023-08-31 23:53 ` Richard Henderson
2023-08-31 20:30 ` [PATCH v2 2/7] target/mips: Re-introduce OPC_ADDUH_QB_DSP and OPC_MUL_PH_DSP Philippe Mathieu-Daudé
` (5 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-31 20:30 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Jiaxun Yang, Aurelien Jarno,
Aleksandar Rikalo, Richard Henderson
Since MULTU opcodes don't record the most significant bits
of the infinite result, sign-extending the sources make no
difference in the result.
Once we remove the sign extension of source registers, MULT
and MULTU are identical (as are DMULT and DMULTU).
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
target/mips/tcg/translate.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 9bb40f1849..e0a76b9432 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -3625,8 +3625,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
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;
--
2.41.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 1/7] target/mips: Simplify Loongson MULTU.G opcode
2023-08-31 20:30 ` [PATCH v2 1/7] target/mips: Simplify Loongson MULTU.G opcode Philippe Mathieu-Daudé
@ 2023-08-31 23:53 ` Richard Henderson
0 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2023-08-31 23:53 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Jiaxun Yang, Aurelien Jarno, Aleksandar Rikalo
On 8/31/23 13:30, Philippe Mathieu-Daudé wrote:
> Since MULTU opcodes don't record the most significant bits
> of the infinite result, sign-extending the sources make no
> difference in the result.
>
> Once we remove the sign extension of source registers, MULT
> and MULTU are identical (as are DMULT and DMULTU).
>
> Suggested-by: Richard Henderson<richard.henderson@linaro.org>
> Signed-off-by: Philippe Mathieu-Daudé<philmd@linaro.org>
> ---
> target/mips/tcg/translate.c | 2 --
> 1 file changed, 2 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 2/7] target/mips: Re-introduce OPC_ADDUH_QB_DSP and OPC_MUL_PH_DSP
2023-08-31 20:30 [PATCH v2 0/7] target/mips: Convert Loongson LEXT opcodes to decodetree Philippe Mathieu-Daudé
2023-08-31 20:30 ` [PATCH v2 1/7] target/mips: Simplify Loongson MULTU.G opcode Philippe Mathieu-Daudé
@ 2023-08-31 20:30 ` Philippe Mathieu-Daudé
2023-08-31 20:30 ` [PATCH v2 3/7] target/mips: Convert Loongson DDIV.G opcodes to decodetree Philippe Mathieu-Daudé
` (4 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-31 20:30 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Jiaxun Yang, Aurelien Jarno,
Aleksandar Rikalo, Philippe Mathieu-Daudé, Richard Henderson
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
There is no issue having multiple enum declarations with
the same value. As we are going to remove the OPC_MULT_G_2E
definition in few commits, restore the OPC_ADDUH_QB_DSP and
OPC_MUL_PH_DSP definitions and use them where they belong.
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
target/mips/tcg/translate.c | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index e0a76b9432..19e73aea60 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -390,16 +390,14 @@ enum {
OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
- /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
- /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
+ OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3,
OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
/* MIPS DSP GPR-Based Shift Sub-class */
OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
/* MIPS DSP Multiply Sub-class insns */
- /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
- /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
+ OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3,
OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
/* DSP Bit/Manipulation Sub-class */
@@ -557,7 +555,6 @@ enum {
OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
};
-#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Arithmetic Sub-class */
@@ -11663,8 +11660,7 @@ static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
gen_load_gpr(v2_t, v2);
switch (op1) {
- /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
- case OPC_MULT_G_2E:
+ case OPC_ADDUH_QB_DSP:
check_dsp_r2(ctx);
switch (op2) {
case OPC_ADDUH_QB:
@@ -12347,11 +12343,7 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
gen_load_gpr(v2_t, v2);
switch (op1) {
- /*
- * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
- * the same mask and op1.
- */
- case OPC_MULT_G_2E:
+ case OPC_MUL_PH_DSP:
check_dsp_r2(ctx);
switch (op2) {
case OPC_MUL_PH:
@@ -13887,7 +13879,7 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
* the same mask and op1.
*/
- if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
+ if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MUL_PH_DSP)) {
op2 = MASK_ADDUH_QB(ctx->opcode);
switch (op2) {
case OPC_ADDUH_QB:
--
2.41.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 3/7] target/mips: Convert Loongson DDIV.G opcodes to decodetree
2023-08-31 20:30 [PATCH v2 0/7] target/mips: Convert Loongson LEXT opcodes to decodetree Philippe Mathieu-Daudé
2023-08-31 20:30 ` [PATCH v2 1/7] target/mips: Simplify Loongson MULTU.G opcode Philippe Mathieu-Daudé
2023-08-31 20:30 ` [PATCH v2 2/7] target/mips: Re-introduce OPC_ADDUH_QB_DSP and OPC_MUL_PH_DSP Philippe Mathieu-Daudé
@ 2023-08-31 20:30 ` Philippe Mathieu-Daudé
2023-08-31 20:30 ` [PATCH v2 4/7] target/mips: Convert Loongson DIV.G " Philippe Mathieu-Daudé
` (3 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-31 20:30 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Jiaxun Yang, Aurelien Jarno,
Aleksandar Rikalo, Philippe Mathieu-Daudé, Richard Henderson
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
Introduce decode_loongson() to decode all Loongson vendor
specific opcodes. Start converting a single opcode: DDIV.G
(divide 64-bit signed integers).
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
target/mips/tcg/translate.h | 1 +
target/mips/tcg/godson2.decode | 16 ++++++
target/mips/tcg/loong-ext.decode | 17 +++++++
target/mips/tcg/loong_translate.c | 85 +++++++++++++++++++++++++++++++
target/mips/tcg/translate.c | 26 ++--------
target/mips/tcg/meson.build | 3 ++
6 files changed, 125 insertions(+), 23 deletions(-)
create mode 100644 target/mips/tcg/godson2.decode
create mode 100644 target/mips/tcg/loong-ext.decode
create mode 100644 target/mips/tcg/loong_translate.c
diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index db3dc932c7..a2365c3c9a 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -220,6 +220,7 @@ bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
+bool decode_ext_loongson(DisasContext *ctx, uint32_t insn);
#if defined(TARGET_MIPS64)
bool decode_ase_lcsr(DisasContext *ctx, uint32_t insn);
bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
new file mode 100644
index 0000000000..382123cc3e
--- /dev/null
+++ b/target/mips/tcg/godson2.decode
@@ -0,0 +1,16 @@
+# Godson2 Integer instructions
+#
+# Copyright (C) 2021 Philippe Mathieu-Daudé
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Reference:
+# Godson-2E Software Manual
+# (Document Number: godson2e-user-manual-V0.6)
+#
+
+&muldiv rs rt rd
+
+@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+
+DDIV_G 011111 ..... ..... ..... 00000 011110 @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
new file mode 100644
index 0000000000..407ca5c78b
--- /dev/null
+++ b/target/mips/tcg/loong-ext.decode
@@ -0,0 +1,17 @@
+# Loongson Extension instructions
+#
+# Copyright (C) 2021 Philippe Mathieu-Daudé
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Reference:
+# STLS2F01 User Manual
+# Appendix A: new integer instructions
+# (Document Number: UM0447)
+#
+
+&muldiv rs rt rd !extern
+
+@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+
+DDIV_G 011100 ..... ..... ..... 00000 010101 @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c b/target/mips/tcg/loong_translate.c
new file mode 100644
index 0000000000..bb329ef027
--- /dev/null
+++ b/target/mips/tcg/loong_translate.c
@@ -0,0 +1,85 @@
+/*
+ * MIPS Loongson translation routines
+ *
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ * Copyright (c) 2006 Marius Groeger (FPU operations)
+ * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
+ * Copyright (c) 2011 Richard Henderson <rth@twiddle.net>
+ * Copyright (c) 2021 Philippe Mathieu-Daudé
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#include "qemu/osdep.h"
+#include "translate.h"
+
+/* Include the auto-generated decoder. */
+#include "decode-godson2.c.inc"
+#include "decode-loong-ext.c.inc"
+
+/*
+ * Word or double-word Fixed-point instructions.
+ * --------------------------------------------
+ *
+ * Fixed-point multiplies and divisions write only one result
+ * into general-purpose registers.
+ */
+
+static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, int rt)
+{
+ TCGv t0, t1;
+ TCGLabel *l1, *l2, *l3;
+
+ 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();
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+ l3 = gen_new_label();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l1);
+
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+ tcg_gen_mov_tl(cpu_gpr[rd], t0);
+
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+ gen_set_label(l3);
+
+ return true;
+}
+
+static bool trans_DDIV_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_DIV_G(s, a->rt, a->rs, a->rd);
+}
+
+bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
+{
+ if ((ctx->insn_flags & INSN_LOONGSON2E)
+ && decode_godson2(ctx, ctx->opcode)) {
+ return true;
+ }
+ if ((ctx->insn_flags & ASE_LEXT)
+ && decode_loong_ext(ctx, ctx->opcode)) {
+ return true;
+ }
+ return false;
+}
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 19e73aea60..42be1689c2 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -334,7 +334,6 @@ enum {
OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
- OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
@@ -376,7 +375,6 @@ enum {
OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
- OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
@@ -3708,25 +3706,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
case OPC_DMULTU_G_2F:
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
break;
- case OPC_DDIV_G_2E:
- case OPC_DDIV_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
- tcg_gen_mov_tl(cpu_gpr[rd], t0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l3);
- }
- break;
case OPC_DDIVU_G_2E:
case OPC_DDIVU_G_2F:
{
@@ -13730,7 +13709,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
break;
case OPC_DMULT_G_2F:
case OPC_DMULTU_G_2F:
- case OPC_DDIV_G_2F:
case OPC_DDIVU_G_2F:
case OPC_DMOD_G_2F:
case OPC_DMODU_G_2F:
@@ -14137,7 +14115,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
}
break;
#if defined(TARGET_MIPS64)
- case OPC_DDIV_G_2E:
case OPC_DDIVU_G_2E:
case OPC_DMULT_G_2E:
case OPC_DMULTU_G_2E:
@@ -15338,6 +15315,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
if (cpu_supports_isa(env, INSN_VR54XX) && decode_ext_vr54xx(ctx, ctx->opcode)) {
return;
}
+ if (decode_ext_loongson(ctx, ctx->opcode)) {
+ return;
+ }
#if defined(TARGET_MIPS64)
if (ase_lcsr_available(env) && decode_ase_lcsr(ctx, ctx->opcode)) {
return;
diff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build
index ea7fb582f2..fbb6d6eb40 100644
--- a/target/mips/tcg/meson.build
+++ b/target/mips/tcg/meson.build
@@ -1,4 +1,6 @@
gen = [
+ decodetree.process('godson2.decode', extra_args: ['--static-decode=decode_godson2']),
+ decodetree.process('loong-ext.decode', extra_args: ['--static-decode=decode_loong_ext']),
decodetree.process('rel6.decode', extra_args: ['--decode=decode_isa_rel6']),
decodetree.process('msa.decode', extra_args: '--decode=decode_ase_msa'),
decodetree.process('tx79.decode', extra_args: '--static-decode=decode_tx79'),
@@ -14,6 +16,7 @@ mips_ss.add(files(
'fpu_helper.c',
'ldst_helper.c',
'lmmi_helper.c',
+ 'loong_translate.c',
'msa_helper.c',
'msa_translate.c',
'op_helper.c',
--
2.41.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 4/7] target/mips: Convert Loongson DIV.G opcodes to decodetree
2023-08-31 20:30 [PATCH v2 0/7] target/mips: Convert Loongson LEXT opcodes to decodetree Philippe Mathieu-Daudé
` (2 preceding siblings ...)
2023-08-31 20:30 ` [PATCH v2 3/7] target/mips: Convert Loongson DDIV.G opcodes to decodetree Philippe Mathieu-Daudé
@ 2023-08-31 20:30 ` Philippe Mathieu-Daudé
2023-08-31 20:30 ` [PATCH v2 5/7] target/mips: Convert Loongson [D]DIVU.G " Philippe Mathieu-Daudé
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-31 20:30 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Jiaxun Yang, Aurelien Jarno,
Aleksandar Rikalo, Philippe Mathieu-Daudé, Richard Henderson
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
DIV.G and DDIV.G are very similar. Provide gen_lext_DIV_G() a
'is_double' argument so it can generate DIV.G (divide 32-bit
signed integers).
With this commit we explicit the template used to generate
opcode for 32/64-bit word variants. Next commits will be less
verbose by providing both variants at once.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
target/mips/tcg/godson2.decode | 1 +
target/mips/tcg/loong-ext.decode | 1 +
target/mips/tcg/loong_translate.c | 28 ++++++++++++++++++++++------
target/mips/tcg/translate.c | 26 --------------------------
4 files changed, 24 insertions(+), 32 deletions(-)
diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
index 382123cc3e..91940c1263 100644
--- a/target/mips/tcg/godson2.decode
+++ b/target/mips/tcg/godson2.decode
@@ -13,4 +13,5 @@
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+DIV_G 011111 ..... ..... ..... 00000 011010 @rs_rt_rd
DDIV_G 011111 ..... ..... ..... 00000 011110 @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
index 407ca5c78b..e9378abc8e 100644
--- a/target/mips/tcg/loong-ext.decode
+++ b/target/mips/tcg/loong-ext.decode
@@ -14,4 +14,5 @@
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+DIV_G 011100 ..... ..... ..... 00000 010100 @rs_rt_rd
DDIV_G 011100 ..... ..... ..... 00000 010101 @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c b/target/mips/tcg/loong_translate.c
index bb329ef027..d42cdb7d2e 100644
--- a/target/mips/tcg/loong_translate.c
+++ b/target/mips/tcg/loong_translate.c
@@ -25,15 +25,18 @@
* into general-purpose registers.
*/
-static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, int rt)
+static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double)
{
TCGv t0, t1;
TCGLabel *l1, *l2, *l3;
- if (TARGET_LONG_BITS != 64) {
- return false;
+ if (is_double) {
+ if (TARGET_LONG_BITS != 64) {
+ return false;
+ }
+ check_mips_64(s);
}
- check_mips_64(s);
if (rd == 0) {
/* Treat as NOP. */
@@ -49,26 +52,39 @@ static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs, int rt)
gen_load_gpr(t0, rs);
gen_load_gpr(t1, rt);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(t0, t0);
+ tcg_gen_ext32s_tl(t1, t1);
+ }
tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
tcg_gen_movi_tl(cpu_gpr[rd], 0);
tcg_gen_br(l3);
gen_set_label(l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, is_double && TARGET_LONG_BITS == 64
+ ? LLONG_MIN : INT_MIN, l2);
tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
tcg_gen_mov_tl(cpu_gpr[rd], t0);
tcg_gen_br(l3);
gen_set_label(l2);
tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
gen_set_label(l3);
return true;
}
+static bool trans_DIV_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_DIV_G(s, a->rt, a->rs, a->rd, false);
+}
+
static bool trans_DDIV_G(DisasContext *s, arg_muldiv *a)
{
- return gen_lext_DIV_G(s, a->rt, a->rs, a->rd);
+ return gen_lext_DIV_G(s, a->rt, a->rs, a->rd, true);
}
bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 42be1689c2..59853f1d87 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -333,7 +333,6 @@ enum {
OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
- OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
@@ -371,7 +370,6 @@ enum {
/* Loongson 2E */
OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
- OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
@@ -3623,28 +3621,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
break;
- case OPC_DIV_G_2E:
- case OPC_DIV_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_ext32s_tl(t0, t0);
- tcg_gen_ext32s_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
- tcg_gen_mov_tl(cpu_gpr[rd], t0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l3);
- }
- break;
case OPC_DIVU_G_2E:
case OPC_DIVU_G_2F:
{
@@ -13674,7 +13650,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
case OPC_MUL:
gen_arith(ctx, op1, rd, rs, rt);
break;
- case OPC_DIV_G_2F:
case OPC_DIVU_G_2F:
case OPC_MULT_G_2F:
case OPC_MULTU_G_2F:
@@ -13847,7 +13822,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
- case OPC_DIV_G_2E:
case OPC_DIVU_G_2E:
case OPC_MOD_G_2E:
case OPC_MODU_G_2E:
--
2.41.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 5/7] target/mips: Convert Loongson [D]DIVU.G opcodes to decodetree
2023-08-31 20:30 [PATCH v2 0/7] target/mips: Convert Loongson LEXT opcodes to decodetree Philippe Mathieu-Daudé
` (3 preceding siblings ...)
2023-08-31 20:30 ` [PATCH v2 4/7] target/mips: Convert Loongson DIV.G " Philippe Mathieu-Daudé
@ 2023-08-31 20:30 ` Philippe Mathieu-Daudé
2023-08-31 20:30 ` [PATCH v2 6/7] target/mips: Convert Loongson [D]MOD[U].G " Philippe Mathieu-Daudé
2023-08-31 20:30 ` [PATCH v2 7/7] target/mips: Convert Loongson [D]MULT[U].G " Philippe Mathieu-Daudé
6 siblings, 0 replies; 11+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-31 20:30 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Jiaxun Yang, Aurelien Jarno,
Aleksandar Rikalo, Philippe Mathieu-Daudé, Richard Henderson
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
Convert DIVU.G (divide 32-bit unsigned integers) and DDIVU.G
(divide 64-bit unsigned integers) opcodes to decodetree.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
target/mips/tcg/godson2.decode | 2 ++
target/mips/tcg/loong-ext.decode | 2 ++
target/mips/tcg/loong_translate.c | 54 +++++++++++++++++++++++++++++++
target/mips/tcg/translate.c | 37 ---------------------
4 files changed, 58 insertions(+), 37 deletions(-)
diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
index 91940c1263..4352d1e5e7 100644
--- a/target/mips/tcg/godson2.decode
+++ b/target/mips/tcg/godson2.decode
@@ -14,4 +14,6 @@
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
DIV_G 011111 ..... ..... ..... 00000 011010 @rs_rt_rd
+DIVU_G 011111 ..... ..... ..... 00000 011011 @rs_rt_rd
DDIV_G 011111 ..... ..... ..... 00000 011110 @rs_rt_rd
+DDIVU_G 011111 ..... ..... ..... 00000 011111 @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
index e9378abc8e..77639227a1 100644
--- a/target/mips/tcg/loong-ext.decode
+++ b/target/mips/tcg/loong-ext.decode
@@ -16,3 +16,5 @@
DIV_G 011100 ..... ..... ..... 00000 010100 @rs_rt_rd
DDIV_G 011100 ..... ..... ..... 00000 010101 @rs_rt_rd
+DIVU_G 011100 ..... ..... ..... 00000 010110 @rs_rt_rd
+DDIVU_G 011100 ..... ..... ..... 00000 010111 @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c b/target/mips/tcg/loong_translate.c
index d42cdb7d2e..87023696a0 100644
--- a/target/mips/tcg/loong_translate.c
+++ b/target/mips/tcg/loong_translate.c
@@ -87,6 +87,60 @@ static bool trans_DDIV_G(DisasContext *s, arg_muldiv *a)
return gen_lext_DIV_G(s, a->rt, a->rs, a->rd, true);
}
+static bool gen_lext_DIVU_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double)
+{
+ TCGv t0, t1;
+ TCGLabel *l1, *l2;
+
+ 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();
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ if (!is_double) {
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ }
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+ gen_set_label(l2);
+
+ return true;
+}
+
+static bool trans_DIVU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_DIVU_G(s, a->rt, a->rs, a->rd, false);
+}
+
+static bool trans_DDIVU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_DIVU_G(s, a->rt, a->rs, a->rd, true);
+}
+
bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
{
if ((ctx->insn_flags & INSN_LOONGSON2E)
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 59853f1d87..f1c99a9218 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -333,8 +333,6 @@ enum {
OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
- OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
- OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
@@ -370,10 +368,8 @@ enum {
/* Loongson 2E */
OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
- OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
- OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
@@ -3621,22 +3617,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
break;
- case OPC_DIVU_G_2E:
- case OPC_DIVU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l2);
- }
- break;
case OPC_MOD_G_2E:
case OPC_MOD_G_2F:
{
@@ -3682,19 +3662,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
case OPC_DMULTU_G_2F:
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
break;
- case OPC_DDIVU_G_2E:
- case OPC_DDIVU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l2);
- }
- break;
case OPC_DMOD_G_2E:
case OPC_DMOD_G_2F:
{
@@ -13650,7 +13617,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
case OPC_MUL:
gen_arith(ctx, op1, rd, rs, rt);
break;
- case OPC_DIVU_G_2F:
case OPC_MULT_G_2F:
case OPC_MULTU_G_2F:
case OPC_MOD_G_2F:
@@ -13684,7 +13650,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
break;
case OPC_DMULT_G_2F:
case OPC_DMULTU_G_2F:
- case OPC_DDIVU_G_2F:
case OPC_DMOD_G_2F:
case OPC_DMODU_G_2F:
check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
@@ -13822,7 +13787,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
- case OPC_DIVU_G_2E:
case OPC_MOD_G_2E:
case OPC_MODU_G_2E:
case OPC_MULT_G_2E:
@@ -14089,7 +14053,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
}
break;
#if defined(TARGET_MIPS64)
- case OPC_DDIVU_G_2E:
case OPC_DMULT_G_2E:
case OPC_DMULTU_G_2E:
case OPC_DMOD_G_2E:
--
2.41.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 6/7] target/mips: Convert Loongson [D]MOD[U].G opcodes to decodetree
2023-08-31 20:30 [PATCH v2 0/7] target/mips: Convert Loongson LEXT opcodes to decodetree Philippe Mathieu-Daudé
` (4 preceding siblings ...)
2023-08-31 20:30 ` [PATCH v2 5/7] target/mips: Convert Loongson [D]DIVU.G " Philippe Mathieu-Daudé
@ 2023-08-31 20:30 ` Philippe Mathieu-Daudé
2023-08-31 20:30 ` [PATCH v2 7/7] target/mips: Convert Loongson [D]MULT[U].G " Philippe Mathieu-Daudé
6 siblings, 0 replies; 11+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-31 20:30 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Jiaxun Yang, Aurelien Jarno,
Aleksandar Rikalo, Philippe Mathieu-Daudé, Richard Henderson
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
Convert the following opcodes to decodetree:
- MOD.G - mod 32-bit signed integers
- MODU.G - mod 32-bit unsigned integers
- DMOD.G - mod 64-bit signed integers
- DMODU.G - mod 64-bit unsigned integers
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
target/mips/tcg/godson2.decode | 5 ++
target/mips/tcg/loong-ext.decode | 5 ++
target/mips/tcg/loong_translate.c | 111 ++++++++++++++++++++++++++++++
target/mips/tcg/translate.c | 82 ----------------------
4 files changed, 121 insertions(+), 82 deletions(-)
diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
index 4352d1e5e7..e3bf6b12e4 100644
--- a/target/mips/tcg/godson2.decode
+++ b/target/mips/tcg/godson2.decode
@@ -17,3 +17,8 @@ DIV_G 011111 ..... ..... ..... 00000 011010 @rs_rt_rd
DIVU_G 011111 ..... ..... ..... 00000 011011 @rs_rt_rd
DDIV_G 011111 ..... ..... ..... 00000 011110 @rs_rt_rd
DDIVU_G 011111 ..... ..... ..... 00000 011111 @rs_rt_rd
+
+MOD_G 011111 ..... ..... ..... 00000 100010 @rs_rt_rd
+MODU_G 011111 ..... ..... ..... 00000 100011 @rs_rt_rd
+DMOD_G 011111 ..... ..... ..... 00000 100110 @rs_rt_rd
+DMODU_G 011111 ..... ..... ..... 00000 100111 @rs_rt_rd
diff --git a/target/mips/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
index 77639227a1..d63406e3f4 100644
--- a/target/mips/tcg/loong-ext.decode
+++ b/target/mips/tcg/loong-ext.decode
@@ -18,3 +18,8 @@ DIV_G 011100 ..... ..... ..... 00000 010100 @rs_rt_rd
DDIV_G 011100 ..... ..... ..... 00000 010101 @rs_rt_rd
DIVU_G 011100 ..... ..... ..... 00000 010110 @rs_rt_rd
DDIVU_G 011100 ..... ..... ..... 00000 010111 @rs_rt_rd
+
+MOD_G 011100 ..... ..... ..... 00000 011100 @rs_rt_rd
+DMOD_G 011100 ..... ..... ..... 00000 011101 @rs_rt_rd
+MODU_G 011100 ..... ..... ..... 00000 011110 @rs_rt_rd
+DMODU_G 011100 ..... ..... ..... 00000 011111 @rs_rt_rd
diff --git a/target/mips/tcg/loong_translate.c b/target/mips/tcg/loong_translate.c
index 87023696a0..bddf1cb7aa 100644
--- a/target/mips/tcg/loong_translate.c
+++ b/target/mips/tcg/loong_translate.c
@@ -141,6 +141,117 @@ static bool trans_DDIVU_G(DisasContext *s, arg_muldiv *a)
return gen_lext_DIVU_G(s, a->rt, a->rs, a->rd, true);
}
+static bool gen_lext_MOD_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double)
+{
+ TCGv t0, t1;
+ TCGLabel *l1, *l2, *l3;
+
+ 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();
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+ l3 = gen_new_label();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ if (!is_double) {
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ }
+ tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, is_double && TARGET_LONG_BITS == 64
+ ? LLONG_MIN : INT_MIN, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+ gen_set_label(l3);
+
+ return true;
+}
+
+static bool trans_MOD_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MOD_G(s, a->rt, a->rs, a->rd, false);
+}
+
+static bool trans_DMOD_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MOD_G(s, a->rt, a->rs, a->rd, true);
+}
+
+static bool gen_lext_MODU_G(DisasContext *s, int rd, int rs, int rt,
+ bool is_double)
+{
+ TCGv t0, t1;
+ TCGLabel *l1, *l2;
+
+ 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();
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ if (!is_double) {
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ }
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+ gen_set_label(l2);
+
+ return true;
+}
+
+static bool trans_MODU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MODU_G(s, a->rt, a->rs, a->rd, false);
+}
+
+static bool trans_DMODU_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MODU_G(s, a->rt, a->rs, a->rd, true);
+}
+
bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
{
if ((ctx->insn_flags & INSN_LOONGSON2E)
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index f1c99a9218..2cfabb3103 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -333,10 +333,6 @@ enum {
OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
- OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
- OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
- OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
- OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
/* Misc */
OPC_CLZ = 0x20 | OPC_SPECIAL2,
OPC_CLO = 0x21 | OPC_SPECIAL2,
@@ -370,10 +366,6 @@ enum {
OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
- OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
- OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
- OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
- OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
/* MIPS DSP Load */
OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
@@ -3617,42 +3609,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
break;
- case OPC_MOD_G_2E:
- case OPC_MOD_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l3);
- }
- break;
- case OPC_MODU_G_2E:
- case OPC_MODU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l2);
- }
- break;
#if defined(TARGET_MIPS64)
case OPC_DMULT_G_2E:
case OPC_DMULT_G_2F:
@@ -3662,36 +3618,6 @@ static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
case OPC_DMULTU_G_2F:
tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
break;
- case OPC_DMOD_G_2E:
- case OPC_DMOD_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l3);
- }
- break;
- case OPC_DMODU_G_2E:
- case OPC_DMODU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l2);
- }
- break;
#endif
}
}
@@ -13619,8 +13545,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
break;
case OPC_MULT_G_2F:
case OPC_MULTU_G_2F:
- case OPC_MOD_G_2F:
- case OPC_MODU_G_2F:
check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
@@ -13650,8 +13574,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
break;
case OPC_DMULT_G_2F:
case OPC_DMULTU_G_2F:
- case OPC_DMOD_G_2F:
- case OPC_DMODU_G_2F:
check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
@@ -13787,8 +13709,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
- case OPC_MOD_G_2E:
- case OPC_MODU_G_2E:
case OPC_MULT_G_2E:
case OPC_MULTU_G_2E:
/*
@@ -14055,8 +13975,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
#if defined(TARGET_MIPS64)
case OPC_DMULT_G_2E:
case OPC_DMULTU_G_2E:
- case OPC_DMOD_G_2E:
- case OPC_DMODU_G_2E:
check_insn(ctx, INSN_LOONGSON2E);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
--
2.41.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 7/7] target/mips: Convert Loongson [D]MULT[U].G opcodes to decodetree
2023-08-31 20:30 [PATCH v2 0/7] target/mips: Convert Loongson LEXT opcodes to decodetree Philippe Mathieu-Daudé
` (5 preceding siblings ...)
2023-08-31 20:30 ` [PATCH v2 6/7] target/mips: Convert Loongson [D]MOD[U].G " Philippe Mathieu-Daudé
@ 2023-08-31 20:30 ` Philippe Mathieu-Daudé
2023-09-01 0:29 ` Richard Henderson
6 siblings, 1 reply; 11+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-31 20:30 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Jiaxun Yang, Aurelien Jarno,
Aleksandar Rikalo, Philippe Mathieu-Daudé
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
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/tcg/godson2.decode | 3 ++
target/mips/tcg/loong-ext.decode | 3 ++
target/mips/tcg/loong_translate.c | 41 +++++++++++++++++
target/mips/tcg/translate.c | 73 +------------------------------
4 files changed, 49 insertions(+), 71 deletions(-)
diff --git a/target/mips/tcg/godson2.decode b/target/mips/tcg/godson2.decode
index e3bf6b12e4..86015ac8e5 100644
--- a/target/mips/tcg/godson2.decode
+++ b/target/mips/tcg/godson2.decode
@@ -13,6 +13,9 @@
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+MULTu_G 011111 ..... ..... ..... 00000 01100- @rs_rt_rd
+DMULTu_G 011111 ..... ..... ..... 00000 01110- @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/tcg/loong-ext.decode b/target/mips/tcg/loong-ext.decode
index d63406e3f4..b05236eb41 100644
--- a/target/mips/tcg/loong-ext.decode
+++ b/target/mips/tcg/loong-ext.decode
@@ -14,6 +14,9 @@
@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &muldiv
+MULTu_G 011100 ..... ..... ..... 00000 0100-0 @rs_rt_rd
+DMULTu_G 011100 ..... ..... ..... 00000 0100-1 @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/tcg/loong_translate.c b/target/mips/tcg/loong_translate.c
index bddf1cb7aa..c896e64b9e 100644
--- a/target/mips/tcg/loong_translate.c
+++ b/target/mips/tcg/loong_translate.c
@@ -252,6 +252,47 @@ 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)
+{
+ 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);
+
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ if (!is_double) {
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ }
+
+ return true;
+}
+
+static bool trans_MULTu_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, false);
+}
+
+static bool trans_DMULTu_G(DisasContext *s, arg_muldiv *a)
+{
+ return gen_lext_MULT_G(s, a->rt, a->rs, a->rd, true);
+}
+
bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
{
if ((ctx->insn_flags & INSN_LOONGSON2E)
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 2cfabb3103..e770840d28 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -328,11 +328,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,
@@ -361,12 +356,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 */
@@ -3582,46 +3571,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;
- }
-
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
- 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_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
- }
-}
-
/* Loongson multimedia instructions */
static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
{
@@ -13543,11 +13492,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);
@@ -13572,11 +13516,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");
@@ -13709,10 +13648,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)) {
@@ -13743,8 +13681,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);
}
@@ -13973,11 +13909,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.41.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2 7/7] target/mips: Convert Loongson [D]MULT[U].G opcodes to decodetree
2023-08-31 20:30 ` [PATCH v2 7/7] target/mips: Convert Loongson [D]MULT[U].G " Philippe Mathieu-Daudé
@ 2023-09-01 0:29 ` Richard Henderson
2024-10-26 15:30 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 11+ messages in thread
From: Richard Henderson @ 2023-09-01 0:29 UTC (permalink / raw)
To: Philippe Mathieu-Daudé, qemu-devel
Cc: Jiaxun Yang, Aurelien Jarno, Aleksandar Rikalo,
Philippe Mathieu-Daudé
On 8/31/23 13:30, Philippe Mathieu-Daudé wrote:
> From: Philippe Mathieu-Daudé <f4bug@amsat.org>
>
> 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>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> + if (is_double) {
> + if (TARGET_LONG_BITS != 64) {
> + return false;
> + }
> + check_mips_64(s);
> + }
This preserves existing behaviour vs
> -#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
this ifdef. But it doesn't seem quite right.
It's a behaviour change between qemu-system-mips and qemu-system-mips64 for the same cpu.
Returning false allows another insn to match instead. But we have identified the insn, it
just isn't legal.
Anyway, aren't all of these loongson cpus 64-bit?
r~
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2 7/7] target/mips: Convert Loongson [D]MULT[U].G opcodes to decodetree
2023-09-01 0:29 ` Richard Henderson
@ 2024-10-26 15:30 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 11+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-10-26 15:30 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
Cc: Jiaxun Yang, Aurelien Jarno, Aleksandar Rikalo,
Philippe Mathieu-Daudé
On 31/8/23 21:29, Richard Henderson wrote:
> On 8/31/23 13:30, Philippe Mathieu-Daudé wrote:
>> From: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>
>> 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>
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>
>
>> + if (is_double) {
>> + if (TARGET_LONG_BITS != 64) {
>> + return false;
>> + }
>> + check_mips_64(s);
>> + }
>
> This preserves existing behaviour vs
>
>> -#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
>
> this ifdef. But it doesn't seem quite right.
>
> It's a behaviour change between qemu-system-mips and qemu-system-mips64
> for the same cpu. Returning false allows another insn to match instead.
> But we have identified the insn, it just isn't legal.
Indeed.
> Anyway, aren't all of these loongson cpus 64-bit?
The Loongson-1 cores family is 32-bit but AFAICT it doesn't implement
the Loongson Extension, which appeared with the Loongson-2 family,
which is 64-bit. QEMU only implement the Loongson-2/3 families, both
64-bit.
I'll post a cleanup patch on top, since this series is already fully
reviewed.
Thanks!
Phil.
^ permalink raw reply [flat|nested] 11+ messages in thread