mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 18:23:57 -06:00
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:
parent
57c108b864
commit
6bf4bbed20
4 changed files with 270 additions and 44 deletions
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue