/*
 * MIPS Loongson 64-bit 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,
                           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_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, 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->rd, a->rs, a->rt, false);
}

static bool trans_DDIV_G(DisasContext *s, arg_muldiv *a)
{
    return gen_lext_DIV_G(s, a->rd, a->rs, a->rt, 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->rd, a->rs, a->rt, false);
}

static bool trans_DDIVU_G(DisasContext *s, arg_muldiv *a)
{
    return gen_lext_DIVU_G(s, a->rd, a->rs, a->rt, 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->rd, a->rs, a->rt, false);
}

static bool trans_DMOD_G(DisasContext *s, arg_muldiv *a)
{
    return gen_lext_MOD_G(s, a->rd, a->rs, a->rt, 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->rd, a->rs, a->rt, false);
}

static bool trans_DMODU_G(DisasContext *s, arg_muldiv *a)
{
    return gen_lext_MODU_G(s, a->rd, a->rs, a->rt, 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->rd, a->rs, a->rt, false);
}

static bool trans_DMULTu_G(DisasContext *s, arg_muldiv *a)
{
    return gen_lext_MULT_G(s, a->rd, a->rs, a->rt, true);
}

bool decode_ext_loongson(DisasContext *ctx, uint32_t insn)
{
    if (!decode_64bit_enabled(ctx)) {
        return false;
    }
    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;
}
