qemu-riscv
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v5 54/60] target/riscv: integer extract instruction


From: LIU Zhiwei
Subject: Re: [PATCH v5 54/60] target/riscv: integer extract instruction
Date: Sun, 15 Mar 2020 13:15:39 +0800
User-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0



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~




reply via email to

[Prev in Thread] Current Thread [Next in Thread]