Skip to content

Commit 90355f3

Browse files
LIU Zhiweialistair23
authored andcommitted
target/riscv: integer extract instruction
Signed-off-by: LIU Zhiwei <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Alistair Francis <[email protected]>
1 parent 126bec3 commit 90355f3

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

target/riscv/insn32.decode

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ vmsif_m 010110 . ..... 00011 010 ..... 1010111 @r2_vm
563563
vmsof_m 010110 . ..... 00010 010 ..... 1010111 @r2_vm
564564
viota_m 010110 . ..... 10000 010 ..... 1010111 @r2_vm
565565
vid_v 010110 . 00000 10001 010 ..... 1010111 @r1_vm
566+
vext_x_v 001100 1 ..... ..... 010 ..... 1010111 @r
566567

567568
vsetvli 0 ........... ..... 111 ..... 1010111 @r2_zimm
568569
vsetvl 1000000 ..... ..... 111 ..... 1010111 @r

target/riscv/insn_trans/trans_rvv.inc.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2533,3 +2533,119 @@ static bool trans_vid_v(DisasContext *s, arg_vid_v *a)
25332533
}
25342534
return false;
25352535
}
2536+
2537+
/*
2538+
*** Vector Permutation Instructions
2539+
*/
2540+
2541+
/* Integer Extract Instruction */
2542+
2543+
static void load_element(TCGv_i64 dest, TCGv_ptr base,
2544+
int ofs, int sew)
2545+
{
2546+
switch (sew) {
2547+
case MO_8:
2548+
tcg_gen_ld8u_i64(dest, base, ofs);
2549+
break;
2550+
case MO_16:
2551+
tcg_gen_ld16u_i64(dest, base, ofs);
2552+
break;
2553+
case MO_32:
2554+
tcg_gen_ld32u_i64(dest, base, ofs);
2555+
break;
2556+
case MO_64:
2557+
tcg_gen_ld_i64(dest, base, ofs);
2558+
break;
2559+
default:
2560+
g_assert_not_reached();
2561+
break;
2562+
}
2563+
}
2564+
2565+
/* offset of the idx element with base regsiter r */
2566+
static uint32_t endian_ofs(DisasContext *s, int r, int idx)
2567+
{
2568+
#ifdef HOST_WORDS_BIGENDIAN
2569+
return vreg_ofs(s, r) + ((idx ^ (7 >> s->sew)) << s->sew);
2570+
#else
2571+
return vreg_ofs(s, r) + (idx << s->sew);
2572+
#endif
2573+
}
2574+
2575+
/* adjust the index according to the endian */
2576+
static void endian_adjust(TCGv_i32 ofs, int sew)
2577+
{
2578+
#ifdef HOST_WORDS_BIGENDIAN
2579+
tcg_gen_xori_i32(ofs, ofs, 7 >> sew);
2580+
#endif
2581+
}
2582+
2583+
/* Load idx >= VLMAX ? 0 : vreg[idx] */
2584+
static void vec_element_loadx(DisasContext *s, TCGv_i64 dest,
2585+
int vreg, TCGv idx, int vlmax)
2586+
{
2587+
TCGv_i32 ofs = tcg_temp_new_i32();
2588+
TCGv_ptr base = tcg_temp_new_ptr();
2589+
TCGv_i64 t_idx = tcg_temp_new_i64();
2590+
TCGv_i64 t_vlmax, t_zero;
2591+
2592+
/*
2593+
* Mask the index to the length so that we do
2594+
* not produce an out-of-range load.
2595+
*/
2596+
tcg_gen_trunc_tl_i32(ofs, idx);
2597+
tcg_gen_andi_i32(ofs, ofs, vlmax - 1);
2598+
2599+
/* Convert the index to an offset. */
2600+
endian_adjust(ofs, s->sew);
2601+
tcg_gen_shli_i32(ofs, ofs, s->sew);
2602+
2603+
/* Convert the index to a pointer. */
2604+
tcg_gen_ext_i32_ptr(base, ofs);
2605+
tcg_gen_add_ptr(base, base, cpu_env);
2606+
2607+
/* Perform the load. */
2608+
load_element(dest, base,
2609+
vreg_ofs(s, vreg), s->sew);
2610+
tcg_temp_free_ptr(base);
2611+
tcg_temp_free_i32(ofs);
2612+
2613+
/* Flush out-of-range indexing to zero. */
2614+
t_vlmax = tcg_const_i64(vlmax);
2615+
t_zero = tcg_const_i64(0);
2616+
tcg_gen_extu_tl_i64(t_idx, idx);
2617+
2618+
tcg_gen_movcond_i64(TCG_COND_LTU, dest, t_idx,
2619+
t_vlmax, dest, t_zero);
2620+
2621+
tcg_temp_free_i64(t_vlmax);
2622+
tcg_temp_free_i64(t_zero);
2623+
tcg_temp_free_i64(t_idx);
2624+
}
2625+
2626+
static void vec_element_loadi(DisasContext *s, TCGv_i64 dest,
2627+
int vreg, int idx)
2628+
{
2629+
load_element(dest, cpu_env, endian_ofs(s, vreg, idx), s->sew);
2630+
}
2631+
2632+
static bool trans_vext_x_v(DisasContext *s, arg_r *a)
2633+
{
2634+
TCGv_i64 tmp = tcg_temp_new_i64();
2635+
TCGv dest = tcg_temp_new();
2636+
2637+
if (a->rs1 == 0) {
2638+
/* Special case vmv.x.s rd, vs2. */
2639+
vec_element_loadi(s, tmp, a->rs2, 0);
2640+
} else {
2641+
/* This instruction ignores LMUL and vector register groups */
2642+
int vlmax = s->vlen >> (3 + s->sew);
2643+
vec_element_loadx(s, tmp, a->rs2, cpu_gpr[a->rs1], vlmax);
2644+
}
2645+
tcg_gen_trunc_i64_tl(dest, tmp);
2646+
gen_set_gpr(a->rd, dest);
2647+
2648+
tcg_temp_free(dest);
2649+
tcg_temp_free_i64(tmp);
2650+
return true;
2651+
}

0 commit comments

Comments
 (0)