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.
Signed-off-by: Philippe Mathieu-Daudé
---
target/mips/godson2.decode| 1 +
target/mips/loong-ext.decode | 1 +
target/mips/loong_translate.c | 28 ++--
target/mips/translate.c | 26 --
4 files changed, 24 insertions(+), 32 deletions(-)
diff --git a/target/mips/godson2.decode b/target/mips/godson2.decode
index cbe22285740..b56a93a1999 100644
--- a/target/mips/godson2.decode
+++ b/target/mips/godson2.decode
@@ -13,4 +13,5 @@
@rs_rt_rd .. rs:5 rt:5 rd:5 . ..
+DIV.G 01 . . . 0 011010 @rs_rt_rd
DDIV.G 01 . . . 0 00 @rs_rt_rd
diff --git a/target/mips/loong-ext.decode b/target/mips/loong-ext.decode
index 557fe06c14a..331c2226ae3 100644
--- a/target/mips/loong-ext.decode
+++ b/target/mips/loong-ext.decode
@@ -14,4 +14,5 @@
@rs_rt_rd .. rs:5 rt:5 rd:5 . ..
+DIV.G 011100 . . . 0 010100 @rs_rt_rd
DDIV.G 011100 . . . 0 010101 @rs_rt_rd
diff --git a/target/mips/loong_translate.c b/target/mips/loong_translate.c
index c452472e7a7..634d4ba8031 100644
--- a/target/mips/loong_translate.c
+++ b/target/mips/loong_translate.c
@@ -27,15 +27,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. */
@@ -51,18 +54,26 @@ 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(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 ? -1LL << 63 : 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);
tcg_temp_free(t0);
@@ -71,9 +82,14 @@ static bool gen_lext_DIV_G(DisasContext *s, int rd, int rs,
int rt)
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_loongson(DisasContext *ctx, uint32_t insn)
diff --git a/target/mips/translate.c b/target/mips/translate.c
index c427ea98952..7cefff44d74 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -342,7 +342,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,
@@ -380,7 +379,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,
@@ -5023,28 +5021,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);
-