mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-01 14:53:54 -06:00

Extra word 2 is stored during tcg compile and `decode_save_opc` needs additional argument in order to pass the value. This will be used during unwind to get extra information about instruction like how to massage exceptions. Updated all callsites as well. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/594 Signed-off-by: Deepak Gupta <debug@rivosinc.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20241008225010.1861630-16-debug@rivosinc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
137 lines
3.9 KiB
C++
137 lines
3.9 KiB
C++
/*
|
|
* 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;
|
|
}
|