target/riscv: support for 128-bit shift instructions

Handling shifts for 32, 64 and 128 operation length for RV128, following the
general framework for handling various olens proposed by Richard.

Signed-off-by: Frédéric Pétrot <frederic.petrot@univ-grenoble-alpes.fr>
Co-authored-by: Fabien Portas <fabien.portas@grenoble-inp.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 20220106210108.138226-13-frederic.petrot@univ-grenoble-alpes.fr
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Frédéric Pétrot 2022-01-06 22:01:02 +01:00 committed by Alistair Francis
parent 57c108b864
commit 6bf4bbed20
4 changed files with 270 additions and 44 deletions

View file

@ -635,7 +635,8 @@ static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
}
static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
void (*func)(TCGv, TCGv, target_long))
void (*func)(TCGv, TCGv, target_long),
void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
{
TCGv dest, src1;
int max_len = get_olen(ctx);
@ -647,26 +648,38 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
dest = dest_gpr(ctx, a->rd);
src1 = get_gpr(ctx, a->rs1, ext);
func(dest, src1, a->shamt);
if (max_len < 128) {
func(dest, src1, a->shamt);
gen_set_gpr(ctx, a->rd, dest);
} else {
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv desth = dest_gprh(ctx, a->rd);
gen_set_gpr(ctx, a->rd, dest);
if (f128 == NULL) {
return false;
}
f128(dest, desth, src1, src1h, a->shamt);
gen_set_gpr128(ctx, a->rd, dest, desth);
}
return true;
}
static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
DisasExtend ext,
void (*f_tl)(TCGv, TCGv, target_long),
void (*f_32)(TCGv, TCGv, target_long))
void (*f_32)(TCGv, TCGv, target_long),
void (*f_128)(TCGv, TCGv, TCGv, TCGv,
target_long))
{
int olen = get_olen(ctx);
if (olen != TARGET_LONG_BITS) {
if (olen == 32) {
f_tl = f_32;
} else {
} else if (olen != 128) {
g_assert_not_reached();
}
}
return gen_shift_imm_fn(ctx, a, ext, f_tl);
return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
}
static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
@ -690,34 +703,49 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
}
static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
void (*func)(TCGv, TCGv, TCGv))
void (*func)(TCGv, TCGv, TCGv),
void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
{
TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, ext);
TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
TCGv ext2 = tcg_temp_new();
int max_len = get_olen(ctx);
tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1);
func(dest, src1, ext2);
tcg_gen_andi_tl(ext2, src2, max_len - 1);
gen_set_gpr(ctx, a->rd, dest);
TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, ext);
if (max_len < 128) {
func(dest, src1, ext2);
gen_set_gpr(ctx, a->rd, dest);
} else {
TCGv src1h = get_gprh(ctx, a->rs1);
TCGv desth = dest_gprh(ctx, a->rd);
if (f128 == NULL) {
return false;
}
f128(dest, desth, src1, src1h, ext2);
gen_set_gpr128(ctx, a->rd, dest, desth);
}
tcg_temp_free(ext2);
return true;
}
static bool gen_shift_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
void (*f_tl)(TCGv, TCGv, TCGv),
void (*f_32)(TCGv, TCGv, TCGv))
void (*f_32)(TCGv, TCGv, TCGv),
void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv))
{
int olen = get_olen(ctx);
if (olen != TARGET_LONG_BITS) {
if (olen == 32) {
f_tl = f_32;
} else {
} else if (olen != 128) {
g_assert_not_reached();
}
}
return gen_shift(ctx, a, ext, f_tl);
return gen_shift(ctx, a, ext, f_tl, f_128);
}
static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext,