/*
 * RISC-V translation routines for the RV64 Zacas Standard Extension.
 *
 * Copyright (c) 2020-2023 PLCT Lab
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2 or later, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#define REQUIRE_ZACAS(ctx) do {          \
    if (!ctx->cfg_ptr->ext_zacas) {      \
        return false;                     \
    }                                     \
} while (0)

static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a)
{
    REQUIRE_ZACAS(ctx);
    return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESL);
}

static TCGv_i64 get_gpr_pair(DisasContext *ctx, int reg_num)
{
    TCGv_i64 t;

    assert(get_ol(ctx) == MXL_RV32);

    if (reg_num == 0) {
        return tcg_constant_i64(0);
    }

    t = tcg_temp_new_i64();
    tcg_gen_concat_tl_i64(t, cpu_gpr[reg_num], cpu_gpr[reg_num + 1]);
    return t;
}

static void gen_set_gpr_pair(DisasContext *ctx, int reg_num, TCGv_i64 t)
{
    assert(get_ol(ctx) == MXL_RV32);

    if (reg_num != 0) {
#ifdef TARGET_RISCV32
        tcg_gen_extr_i64_i32(cpu_gpr[reg_num], cpu_gpr[reg_num + 1], t);
#else
        tcg_gen_ext32s_i64(cpu_gpr[reg_num], t);
        tcg_gen_sari_i64(cpu_gpr[reg_num + 1], t, 32);
#endif

        if (get_xl_max(ctx) == MXL_RV128) {
            tcg_gen_sari_tl(cpu_gprh[reg_num], cpu_gpr[reg_num], 63);
            tcg_gen_sari_tl(cpu_gprh[reg_num + 1], cpu_gpr[reg_num + 1], 63);
        }
    }
}

static bool gen_cmpxchg64(DisasContext *ctx, arg_atomic *a, MemOp mop)
{
    /*
     * Encodings with odd numbered registers specified in rs2 and rd are
     * reserved.
     */
    if ((a->rs2 | a->rd) & 1) {
        return false;
    }

    TCGv_i64 dest = get_gpr_pair(ctx, a->rd);
    TCGv src1 = get_address(ctx, a->rs1, 0);
    TCGv_i64 src2 = get_gpr_pair(ctx, a->rs2);

    decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
    tcg_gen_atomic_cmpxchg_i64(dest, src1, dest, src2, ctx->mem_idx, mop);

    gen_set_gpr_pair(ctx, a->rd, dest);
    return true;
}

static bool trans_amocas_d(DisasContext *ctx, arg_amocas_d *a)
{
    REQUIRE_ZACAS(ctx);
    switch (get_ol(ctx)) {
    case MXL_RV32:
        return gen_cmpxchg64(ctx, a, MO_ALIGN | MO_TEUQ);
    case MXL_RV64:
    case MXL_RV128:
        return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TEUQ);
    default:
        g_assert_not_reached();
    }
}

static bool trans_amocas_q(DisasContext *ctx, arg_amocas_q *a)
{
    REQUIRE_ZACAS(ctx);
    REQUIRE_64BIT(ctx);

    /*
     * Encodings with odd numbered registers specified in rs2 and rd are
     * reserved.
     */
    if ((a->rs2 | a->rd) & 1) {
        return false;
    }

#ifdef TARGET_RISCV64
    TCGv_i128 dest = tcg_temp_new_i128();
    TCGv src1 = get_address(ctx, a->rs1, 0);
    TCGv_i128 src2 = tcg_temp_new_i128();
    TCGv_i64 src2l = get_gpr(ctx, a->rs2, EXT_NONE);
    TCGv_i64 src2h = get_gpr(ctx, a->rs2 == 0 ? 0 : a->rs2 + 1, EXT_NONE);
    TCGv_i64 destl = get_gpr(ctx, a->rd, EXT_NONE);
    TCGv_i64 desth = get_gpr(ctx, a->rd == 0 ? 0 : a->rd + 1, EXT_NONE);

    tcg_gen_concat_i64_i128(src2, src2l, src2h);
    tcg_gen_concat_i64_i128(dest, destl, desth);
    decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
    tcg_gen_atomic_cmpxchg_i128(dest, src1, dest, src2, ctx->mem_idx,
                                (MO_ALIGN | MO_TEUO));

    tcg_gen_extr_i128_i64(destl, desth, dest);

    if (a->rd != 0) {
        gen_set_gpr(ctx, a->rd, destl);
        gen_set_gpr(ctx, a->rd + 1, desth);
    }
#endif

    return true;
}
