On 2020/3/15 10:53, Richard Henderson wrote:
On 3/12/20 7:58 AM, LIU Zhiwei wrote:
+static bool trans_vext_x_v(DisasContext *s, arg_r *a)
+{
+ if (vext_check_isa_ill(s, RVV)) {
+ TCGv_ptr src2;
+ TCGv dest, src1;
+ gen_helper_vext_x_v fns[4] = {
+ gen_helper_vext_x_v_b, gen_helper_vext_x_v_h,
+ gen_helper_vext_x_v_w, gen_helper_vext_x_v_d
+ };
+
+ dest = tcg_temp_new();
+ src1 = tcg_temp_new();
+ src2 = tcg_temp_new_ptr();
+
+ gen_get_gpr(src1, a->rs1);
+ tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2));
+
+ fns[s->sew](dest, src2, src1, cpu_env);
+ gen_set_gpr(a->rd, dest);
+
+ tcg_temp_free(dest);
+ tcg_temp_free(src1);
+ tcg_temp_free_ptr(src2);
+ return true;
+ }
+ return false;
+}
This entire operation can be performed inline easily.
static void extract_element(TCGv dest, TCGv_ptr base,
int ofs, int sew)
{
switch (sew) {
case MO_8:
tcg_gen_ld8u_tl(dest, base, ofs);
break;
case MO_16:
tcg_gen_ld16u_tl(dest, base, ofs);
break;
default:
tcg_gen_ld32u_tl(dest, base, ofs);
break;
#if TARGET_LONG_BITS == 64
case MO_64:
tcg_gen_ld_i64(dest, base, ofs);
break;
#endif
}
}
static bool trans_vext_x_v(DisasContext *s, arg_r *a)
{
...
if (a->rs1 == 0) {
/* Special case vmv.x.s rd, vs2. */
do_extract(dest, cpu_env,
vreg_ofs(s, a->rs2), s->sew);
} else {
int vlen = s->vlen >> (3 + s->sew);
TCGv_i32 ofs = tcg_temp_new_i32();
TCGv_ptr base = tcg_temp_new_ptr();
TCGv t_vlen, t_zero;
/* Mask the index to the length so that we do
not produce an out-of-range load. */
tcg_gen_trunc_tl_i32(ofs, cpu_gpr[a->rs1]);
tcg_gen_andi_i32(ofs, ofs, vlen - 1);
/* Convert the index to an offset. */
tcg_gen_shli_i32(ofs, ofs, s->sew);
InĀ big endianess host, should I convert the index first before this
statement.
#ifdef HOST_WORDS_BIGENDIAN
static void convert_idx(TCGv_i32 idx, int sew)
{
switch (sew) {
case MO_8:
tcg_gen_xori_i32(idx, idx, 7);
break;
case MO_16:
tcg_gen_xori_i32(idx, idx, 3);
break;
case MO_32:
tcg_gen_xori_i32(idx, idx, 1);
break;
default:
break;
}
}
#endif
When convert the index to an offset, use this function first
#ifdef HOST_WORDS_BIGENDIAN
convert_idx(ofs, s->sew)
#endif
/* Convert the index to an offset. */
tcg_gen_shli_i32(ofs, ofs, s->sew)
Zhiwei
/* Convert the index to a pointer. */
tcg_gen_extu_i32_ptr(base, ofs);
tcg_gen_add_ptr(base, base, cpu_env);
/* Perform the load. */
do_extract(dest, base,
vreg_ofs(s, a->rs2), s->sew);
tcg_temp_free_ptr(base);
tcg_temp_free_i32(ofs);
/* Flush out-of-range indexing to zero. */
t_vlen = tcg_const_tl(vlen);
t_zero = tcg_const_tl(0);
tcg_gen_movcond_tl(TCG_COND_LTU, dest, cpu_gpr[a->rs1],
t_vlen, dest, t_zero);
tcg_temp_free(t_vlen);
tcg_temp_free(t_zero);
}
r~