diff mbox series

[v3,4/4] RISC-V: add vector extension configure instruction

Message ID 20200103033347.20909-5-zhiwei_liu@c-sky.com (mailing list archive)
State New, archived
Headers show
Series RISC-V: support vector extension part 1 | expand

Commit Message

LIU Zhiwei Jan. 3, 2020, 3:33 a.m. UTC
vsetvl and vsetvli are two configure instructions for vl, vtype. TB flags
should update after configure instructions. The (ill, lmul, sew ) of vtype
and the bit of (VSTART == 0 && VL == VLMAX) will be placed within tb_flags.

Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
---
 target/riscv/Makefile.objs              |  2 +-
 target/riscv/cpu.c                      |  1 +
 target/riscv/cpu.h                      | 55 ++++++++++++++++++++-----
 target/riscv/helper.h                   |  2 +
 target/riscv/insn32.decode              |  5 +++
 target/riscv/insn_trans/trans_rvv.inc.c | 52 +++++++++++++++++++++++
 target/riscv/translate.c                | 17 +++++++-
 target/riscv/vector_helper.c            | 51 +++++++++++++++++++++++
 8 files changed, 172 insertions(+), 13 deletions(-)
 create mode 100644 target/riscv/insn_trans/trans_rvv.inc.c
 create mode 100644 target/riscv/vector_helper.c

Comments

Richard Henderson Jan. 3, 2020, 11:41 p.m. UTC | #1
On 1/3/20 2:33 PM, LIU Zhiwei wrote:
> vsetvl and vsetvli are two configure instructions for vl, vtype. TB flags
> should update after configure instructions. The (ill, lmul, sew ) of vtype
> and the bit of (VSTART == 0 && VL == VLMAX) will be placed within tb_flags.
> 
> Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
> ---
>  target/riscv/Makefile.objs              |  2 +-
>  target/riscv/cpu.c                      |  1 +
>  target/riscv/cpu.h                      | 55 ++++++++++++++++++++-----
>  target/riscv/helper.h                   |  2 +
>  target/riscv/insn32.decode              |  5 +++
>  target/riscv/insn_trans/trans_rvv.inc.c | 52 +++++++++++++++++++++++
>  target/riscv/translate.c                | 17 +++++++-
>  target/riscv/vector_helper.c            | 51 +++++++++++++++++++++++
>  8 files changed, 172 insertions(+), 13 deletions(-)
>  create mode 100644 target/riscv/insn_trans/trans_rvv.inc.c
>  create mode 100644 target/riscv/vector_helper.c
> 
> diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
> index b1c79bc1d1..d577cef9e0 100644
> --- a/target/riscv/Makefile.objs
> +++ b/target/riscv/Makefile.objs
> @@ -1,4 +1,4 @@
> -obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o pmp.o
> +obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o vector_helper.o gdbstub.o pmp.o
>  
>  DECODETREE = $(SRC_PATH)/scripts/decodetree.py
>  
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index c2370a0a57..3ff7b50bff 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -347,6 +347,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
>          }
>      }
>      if (cpu->cfg.vext_spec) {
> +        env->vext.vtype = ~((target_ulong)-1 >> 1);

Better as FIELD_DP64(0, VTYPE, VILL, 1),


> +struct VTYPE {
> +#ifdef HOST_WORDS_BIGENDIAN
> +    target_ulong vill:1;
> +    target_ulong reserved:sizeof(target_ulong) * 8 - 7;
> +    target_ulong sew:3;
> +    target_ulong lmul:2;
> +#else
> +    target_ulong lmul:2;
> +    target_ulong sew:3;
> +    target_ulong reserved:sizeof(target_ulong) * 8 - 7;
> +    target_ulong vill:1;
> +#endif
> +};

Do not use bit fields to describe target register layout.
Use FIELD().

> -#define TB_FLAGS_MMU_MASK   3
> -#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
> +typedef CPURISCVState CPUArchState;
> +typedef RISCVCPU ArchCPU;
> +#include "exec/cpu-all.h"
> +
> +FIELD(TB_FLAGS, MMU, 0, 2)
> +FIELD(TB_FLAGS, FS, 13, 2)

The change to use FIELD for MMU and FS should be made separately from adding
the vector state.

> +FIELD(TB_FLAGS, VL_EQ_VLMAX, 16, 1)
> +FIELD(TB_FLAGS, LMUL, 17, 2)
> +FIELD(TB_FLAGS, SEW, 19, 3)
> +FIELD(TB_FLAGS, VILL, 22, 1)

Why are you leaving holes in TB_FLAGS?  I know why the original hole was there,
since it corresponded to simple masks on other registers.

> +    vlmax = (1 << vtype->lmul) * cpu->cfg.vlen / (8 * (1 << vtype->sew));

Wow, this can be simplified a lot.

   (1 << LMUL) * VLEN / (8 * (1 << SEW))
 = (VLEN << LMUL) / (8 << SEW)
 = (VLEN << LMUL) >> (SEW + 3)
 = VLEN >> (SEW + 3 - LMUL)


> +    vl_eq_vlmax = (env->vext.vstart == 0) && (vlmax == env->vext.vl);
> +
> +    flags = FIELD_DP32(flags, TB_FLAGS, VILL, vtype->vill);
> +    flags = FIELD_DP32(flags, TB_FLAGS, SEW, vtype->sew);
> +    flags = FIELD_DP32(flags, TB_FLAGS, LMUL, vtype->lmul);
> +    flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);

I wonder if perhaps this all ought to be nested under

  if (env->misa & RVV) {
      ...
  } else {
      flag = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
  }

so that, for the normal case when RVV is disabled, we don't bother computing
all of those bits.

> +static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl * a)
> +{
> +    TCGv s1, s2, d;
> +    d = tcg_temp_new();
> +    s1 = tcg_temp_new();
> +    s2 = tcg_temp_new();
> +    gen_get_gpr(s1, a->rs1);
> +    gen_get_gpr(s2, a->rs2);
> +    gen_helper_vector_vsetvli(d, cpu_env, s1, s2);
> +    tcg_gen_st_tl(d, cpu_env, offsetof(CPURISCVState, vext.vl));

Why are you performing the store to vl inline, as opposed to within the helper
funtion?

> +    exit_tb(ctx);

A normal exit is correct for vsetvl, because the new state is variable.

> +static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli * a)
> +{
> +    TCGv s1, s2, d;
> +    d = tcg_temp_new();
> +    s1 = tcg_temp_new();
> +    s2 = tcg_const_tl(a->zimm);
> +    gen_get_gpr(s1, a->rs1);
> +    gen_helper_vector_vsetvli(d, cpu_env, s1, s2);
> +    tcg_gen_st_tl(d, cpu_env, offsetof(CPURISCVState, vext.vl));
> +    exit_tb(ctx);

You could use

  gen_goto_tb(ctx, 0, ctx->base.pc_next)

here, because the new state is unknown but constant.  It will be the same every
time the instruction is executed, and thus can compute the new state only once,
saving that computation in the link to the next tb.

> +target_ulong VECTOR_HELPER(vsetvli)(CPURISCVState *env, target_ulong s1,
> +    target_ulong s2)
> +{
> +    int vlmax, vl;
> +    RISCVCPU *cpu = env_archcpu(env);
> +    struct VTYPE *vtype = (struct VTYPE *)&s2;

FIELD_EX64 for all uses of VTYPE.

> +
> +    if (vtype->sew > cpu->cfg.elen) { /* only set vill bit. */
> +        env->vext.vtype = ~((target_ulong)-1 >> 1);

FIELD_DP64.

> +    vlmax = (1 << vtype->lmul) * cpu->cfg.vlen / (8 * (1 << vtype->sew));

Same simplification as before.  Perhaps extract this to an inline function for
clarity, documenting the algebraic simplification only once.


r~
LIU Zhiwei Jan. 7, 2020, 2:11 a.m. UTC | #2
Hi Richard,

Thanks for the comments of the part 1.  It's really very helpful.
I accept most of the comments.

On 2020/1/4 7:41, Richard Henderson wrote:
> On 1/3/20 2:33 PM, LIU Zhiwei wrote:
>> vsetvl and vsetvli are two configure instructions for vl, vtype. TB flags
>> should update after configure instructions. The (ill, lmul, sew ) of vtype
>> and the bit of (VSTART == 0 && VL == VLMAX) will be placed within tb_flags.
>>
>> Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
>> ---
>>   target/riscv/Makefile.objs              |  2 +-
>>   target/riscv/cpu.c                      |  1 +
>>   target/riscv/cpu.h                      | 55 ++++++++++++++++++++-----
>>   target/riscv/helper.h                   |  2 +
>>   target/riscv/insn32.decode              |  5 +++
>>   target/riscv/insn_trans/trans_rvv.inc.c | 52 +++++++++++++++++++++++
>>   target/riscv/translate.c                | 17 +++++++-
>>   target/riscv/vector_helper.c            | 51 +++++++++++++++++++++++
>>   8 files changed, 172 insertions(+), 13 deletions(-)
>>   create mode 100644 target/riscv/insn_trans/trans_rvv.inc.c
>>   create mode 100644 target/riscv/vector_helper.c
>>
>> diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
>> index b1c79bc1d1..d577cef9e0 100644
>> --- a/target/riscv/Makefile.objs
>> +++ b/target/riscv/Makefile.objs
>> @@ -1,4 +1,4 @@
>> -obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o pmp.o
>> +obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o vector_helper.o gdbstub.o pmp.o
>>   
>>   DECODETREE = $(SRC_PATH)/scripts/decodetree.py
>>   
>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> index c2370a0a57..3ff7b50bff 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -347,6 +347,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
>>           }
>>       }
>>       if (cpu->cfg.vext_spec) {
>> +        env->vext.vtype = ~((target_ulong)-1 >> 1);
> Better as FIELD_DP64(0, VTYPE, VILL, 1),
>
>
>> +struct VTYPE {
>> +#ifdef HOST_WORDS_BIGENDIAN
>> +    target_ulong vill:1;
>> +    target_ulong reserved:sizeof(target_ulong) * 8 - 7;
>> +    target_ulong sew:3;
>> +    target_ulong lmul:2;
>> +#else
>> +    target_ulong lmul:2;
>> +    target_ulong sew:3;
>> +    target_ulong reserved:sizeof(target_ulong) * 8 - 7;
>> +    target_ulong vill:1;
>> +#endif
>> +};
> Do not use bit fields to describe target register layout.
> Use FIELD().
OK. I think there is no need to the handle endianess here.  FIELD() is good.

>> -#define TB_FLAGS_MMU_MASK   3
>> -#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
>> +typedef CPURISCVState CPUArchState;
>> +typedef RISCVCPU ArchCPU;
>> +#include "exec/cpu-all.h"
>> +
>> +FIELD(TB_FLAGS, MMU, 0, 2)
>> +FIELD(TB_FLAGS, FS, 13, 2)
> The change to use FIELD for MMU and FS should be made separately from adding
> the vector state.
>
>> +FIELD(TB_FLAGS, VL_EQ_VLMAX, 16, 1)
>> +FIELD(TB_FLAGS, LMUL, 17, 2)
>> +FIELD(TB_FLAGS, SEW, 19, 3)
>> +FIELD(TB_FLAGS, VILL, 22, 1)
> Why are you leaving holes in TB_FLAGS?  I know why the original hole was there,
> since it corresponded to simple masks on other registers.
>
>> +    vlmax = (1 << vtype->lmul) * cpu->cfg.vlen / (8 * (1 << vtype->sew));
> Wow, this can be simplified a lot.
>
>     (1 << LMUL) * VLEN / (8 * (1 << SEW))
>   = (VLEN << LMUL) / (8 << SEW)
>   = (VLEN << LMUL) >> (SEW + 3)
>   = VLEN >> (SEW + 3 - LMUL)
>
Good.
>> +    vl_eq_vlmax = (env->vext.vstart == 0) && (vlmax == env->vext.vl);
>> +
>> +    flags = FIELD_DP32(flags, TB_FLAGS, VILL, vtype->vill);
>> +    flags = FIELD_DP32(flags, TB_FLAGS, SEW, vtype->sew);
>> +    flags = FIELD_DP32(flags, TB_FLAGS, LMUL, vtype->lmul);
>> +    flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
> I wonder if perhaps this all ought to be nested under
>
>    if (env->misa & RVV) {
>        ...
>    } else {
>        flag = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
>    }
>
> so that, for the normal case when RVV is disabled, we don't bother computing
> all of those bits.
>
>> +static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl * a)
>> +{
>> +    TCGv s1, s2, d;
>> +    d = tcg_temp_new();
>> +    s1 = tcg_temp_new();
>> +    s2 = tcg_temp_new();
>> +    gen_get_gpr(s1, a->rs1);
>> +    gen_get_gpr(s2, a->rs2);
>> +    gen_helper_vector_vsetvli(d, cpu_env, s1, s2);
>> +    tcg_gen_st_tl(d, cpu_env, offsetof(CPURISCVState, vext.vl));
> Why are you performing the store to vl inline, as opposed to within the helper
> funtion?
>
>> +    exit_tb(ctx);
> A normal exit is correct for vsetvl, because the new state is variable.
>
>> +static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli * a)
>> +{
>> +    TCGv s1, s2, d;
>> +    d = tcg_temp_new();
>> +    s1 = tcg_temp_new();
>> +    s2 = tcg_const_tl(a->zimm);
>> +    gen_get_gpr(s1, a->rs1);
>> +    gen_helper_vector_vsetvli(d, cpu_env, s1, s2);
>> +    tcg_gen_st_tl(d, cpu_env, offsetof(CPURISCVState, vext.vl));
>> +    exit_tb(ctx);
> You could use
>
>    gen_goto_tb(ctx, 0, ctx->base.pc_next)
>
> here, because the new state is unknown but constant.  It will be the same every
> time the instruction is executed, and thus can compute the new state only once,
> saving that computation in the link to the next tb.
>
>> +target_ulong VECTOR_HELPER(vsetvli)(CPURISCVState *env, target_ulong s1,
>> +    target_ulong s2)
>> +{
>> +    int vlmax, vl;
>> +    RISCVCPU *cpu = env_archcpu(env);
>> +    struct VTYPE *vtype = (struct VTYPE *)&s2;
> FIELD_EX64 for all uses of VTYPE.
>
>> +
>> +    if (vtype->sew > cpu->cfg.elen) { /* only set vill bit. */
>> +        env->vext.vtype = ~((target_ulong)-1 >> 1);
> FIELD_DP64.
>
>> +    vlmax = (1 << vtype->lmul) * cpu->cfg.vlen / (8 * (1 << vtype->sew));
> Same simplification as before.  Perhaps extract this to an inline function for
> clarity, documenting the algebraic simplification only once.
>
> r~
Best Regards,
Zhiwei
diff mbox series

Patch

diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
index b1c79bc1d1..d577cef9e0 100644
--- a/target/riscv/Makefile.objs
+++ b/target/riscv/Makefile.objs
@@ -1,4 +1,4 @@ 
-obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o pmp.o
+obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o vector_helper.o gdbstub.o pmp.o
 
 DECODETREE = $(SRC_PATH)/scripts/decodetree.py
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index c2370a0a57..3ff7b50bff 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -347,6 +347,7 @@  static void riscv_cpu_realize(DeviceState *dev, Error **errp)
         }
     }
     if (cpu->cfg.vext_spec) {
+        env->vext.vtype = ~((target_ulong)-1 >> 1);
         if (!g_strcmp0(cpu->cfg.vext_spec, "v0.7.1")) {
             vext_version = VEXT_VERSION_0_07_1;
         } else {
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index d0b106583a..152a96f1fa 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -23,6 +23,7 @@ 
 #include "qom/cpu.h"
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat.h"
+#include "hw/registerfields.h"
 
 #define TCG_GUEST_DEFAULT_MO 0
 
@@ -98,6 +99,20 @@  typedef struct CPURISCVState CPURISCVState;
 
 #define RV_VLEN_MAX 4096
 
+struct VTYPE {
+#ifdef HOST_WORDS_BIGENDIAN
+    target_ulong vill:1;
+    target_ulong reserved:sizeof(target_ulong) * 8 - 7;
+    target_ulong sew:3;
+    target_ulong lmul:2;
+#else
+    target_ulong lmul:2;
+    target_ulong sew:3;
+    target_ulong reserved:sizeof(target_ulong) * 8 - 7;
+    target_ulong vill:1;
+#endif
+};
+
 struct CPURISCVState {
     target_ulong gpr[32];
     uint64_t fpr[32]; /* assume both F and D extensions */
@@ -309,19 +324,44 @@  void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
 target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
 void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
 
-#define TB_FLAGS_MMU_MASK   3
-#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
+typedef CPURISCVState CPUArchState;
+typedef RISCVCPU ArchCPU;
+#include "exec/cpu-all.h"
+
+FIELD(TB_FLAGS, MMU, 0, 2)
+FIELD(TB_FLAGS, FS, 13, 2)
+FIELD(TB_FLAGS, VL_EQ_VLMAX, 16, 1)
+FIELD(TB_FLAGS, LMUL, 17, 2)
+FIELD(TB_FLAGS, SEW, 19, 3)
+FIELD(TB_FLAGS, VILL, 22, 1)
 
 static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
-                                        target_ulong *cs_base, uint32_t *flags)
+                                        target_ulong *cs_base, uint32_t *pflags)
 {
+    RISCVCPU *cpu = env_archcpu(env);
+    struct VTYPE *vtype = (struct VTYPE *)&env->vext.vtype;
+    uint32_t vlmax;
+    uint8_t vl_eq_vlmax;
+    uint32_t flags = 0;
+
     *pc = env->pc;
     *cs_base = 0;
+    vlmax = (1 << vtype->lmul) * cpu->cfg.vlen / (8 * (1 << vtype->sew));
+    vl_eq_vlmax = (env->vext.vstart == 0) && (vlmax == env->vext.vl);
+
+    flags = FIELD_DP32(flags, TB_FLAGS, VILL, vtype->vill);
+    flags = FIELD_DP32(flags, TB_FLAGS, SEW, vtype->sew);
+    flags = FIELD_DP32(flags, TB_FLAGS, LMUL, vtype->lmul);
+    flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
+
 #ifdef CONFIG_USER_ONLY
-    *flags = TB_FLAGS_MSTATUS_FS;
+    flags = FIELD_DP32(flags, TB_FLAGS, FS, MSTATUS_FS);
 #else
-    *flags = cpu_mmu_index(env, 0) | (env->mstatus & MSTATUS_FS);
+    flags = FIELD_DP32(flags, TB_FLAGS, MMU, cpu_mmu_index(env, 0));
+    flags = FIELD_DP32(flags, TB_FLAGS, FS, (env->mstatus & MSTATUS_FS));
 #endif
+    *pflags = flags;
+    *cs_base = 0;
 }
 
 int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
@@ -362,9 +402,4 @@  void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
 
 void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
 
-typedef CPURISCVState CPUArchState;
-typedef RISCVCPU ArchCPU;
-
-#include "exec/cpu-all.h"
-
 #endif /* RISCV_CPU_H */
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index debb22a480..000b5aa3d1 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -76,3 +76,5 @@  DEF_HELPER_2(mret, tl, env, tl)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(tlb_flush, void, env)
 #endif
+/* Vector functions */
+DEF_HELPER_3(vector_vsetvli, tl, env, tl, tl)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 77f794ed70..5dc009c3cd 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -62,6 +62,7 @@ 
 @r_rm    .......   ..... ..... ... ..... ....... %rs2 %rs1 %rm %rd
 @r2_rm   .......   ..... ..... ... ..... ....... %rs1 %rm %rd
 @r2      .......   ..... ..... ... ..... ....... %rs1 %rd
+@r2_zimm . zimm:11  ..... ... ..... ....... %rs1 %rd
 
 @sfence_vma ....... ..... .....   ... ..... ....... %rs2 %rs1
 @sfence_vm  ....... ..... .....   ... ..... ....... %rs1
@@ -203,3 +204,7 @@  fcvt_w_d   1100001  00000 ..... ... ..... 1010011 @r2_rm
 fcvt_wu_d  1100001  00001 ..... ... ..... 1010011 @r2_rm
 fcvt_d_w   1101001  00000 ..... ... ..... 1010011 @r2_rm
 fcvt_d_wu  1101001  00001 ..... ... ..... 1010011 @r2_rm
+
+# *** RV32V Extension ***
+vsetvli         0 ........... ..... 111 ..... 1010111  @r2_zimm
+vsetvl          1000000 ..... ..... 111 ..... 1010111  @r
diff --git a/target/riscv/insn_trans/trans_rvv.inc.c b/target/riscv/insn_trans/trans_rvv.inc.c
new file mode 100644
index 0000000000..5d80144502
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvv.inc.c
@@ -0,0 +1,52 @@ 
+/*
+ * RISC-V translation routines for the RVV Standard Extension.
+ *
+ * Copyright (c) 2019 C-SKY Limited. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl * a)
+{
+    TCGv s1, s2, d;
+    d = tcg_temp_new();
+    s1 = tcg_temp_new();
+    s2 = tcg_temp_new();
+    gen_get_gpr(s1, a->rs1);
+    gen_get_gpr(s2, a->rs2);
+    gen_helper_vector_vsetvli(d, cpu_env, s1, s2);
+    tcg_gen_st_tl(d, cpu_env, offsetof(CPURISCVState, vext.vl));
+    exit_tb(ctx);
+    ctx->base.is_jmp = DISAS_NORETURN;
+    tcg_temp_free(s1);
+    tcg_temp_free(s2);
+    tcg_temp_free(d);
+    return true;
+}
+
+static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli * a)
+{
+    TCGv s1, s2, d;
+    d = tcg_temp_new();
+    s1 = tcg_temp_new();
+    s2 = tcg_const_tl(a->zimm);
+    gen_get_gpr(s1, a->rs1);
+    gen_helper_vector_vsetvli(d, cpu_env, s1, s2);
+    tcg_gen_st_tl(d, cpu_env, offsetof(CPURISCVState, vext.vl));
+    exit_tb(ctx);
+    ctx->base.is_jmp = DISAS_NORETURN;
+    tcg_temp_free(s1);
+    tcg_temp_free(s2);
+    tcg_temp_free(d);
+    return true;
+}
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 8d6ab73258..beb283b735 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -55,6 +55,12 @@  typedef struct DisasContext {
        to reset this known value.  */
     int frm;
     bool ext_ifencei;
+    /* vector extension */
+    bool vill;
+    uint8_t lmul;
+    uint8_t sew;
+    uint16_t vlen;
+    bool vl_eq_vlmax;
 } DisasContext;
 
 #ifdef TARGET_RISCV64
@@ -706,6 +712,7 @@  static bool gen_shift(DisasContext *ctx, arg_r *a,
 #include "insn_trans/trans_rva.inc.c"
 #include "insn_trans/trans_rvf.inc.c"
 #include "insn_trans/trans_rvd.inc.c"
+#include "insn_trans/trans_rvv.inc.c"
 #include "insn_trans/trans_privileged.inc.c"
 
 /*
@@ -754,14 +761,20 @@  static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
     CPURISCVState *env = cs->env_ptr;
     RISCVCPU *cpu = RISCV_CPU(cs);
+    uint32_t tb_flags = ctx->base.tb->flags;
 
     ctx->pc_succ_insn = ctx->base.pc_first;
-    ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
-    ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
+    ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MMU);
+    ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
     ctx->priv_ver = env->priv_ver;
     ctx->misa = env->misa;
     ctx->frm = -1;  /* unknown rounding mode */
     ctx->ext_ifencei = cpu->cfg.ext_ifencei;
+    ctx->vlen = cpu->cfg.vlen;
+    ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
+    ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
+    ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);
+    ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
 }
 
 static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
new file mode 100644
index 0000000000..4e394207ce
--- /dev/null
+++ b/target/riscv/vector_helper.c
@@ -0,0 +1,51 @@ 
+/*
+ * RISC-V Vectore Extension Helpers for QEMU.
+ *
+ * Copyright (c) 2019 C-SKY Limited. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "exec/helper-proto.h"
+#include <math.h>
+
+#define VECTOR_HELPER(name) HELPER(glue(vector_, name))
+
+target_ulong VECTOR_HELPER(vsetvli)(CPURISCVState *env, target_ulong s1,
+    target_ulong s2)
+{
+    int vlmax, vl;
+    RISCVCPU *cpu = env_archcpu(env);
+    struct VTYPE *vtype = (struct VTYPE *)&s2;
+
+    if (vtype->sew > cpu->cfg.elen) { /* only set vill bit. */
+        env->vext.vtype = ~((target_ulong)-1 >> 1);
+        return 0;
+    }
+
+    vlmax = (1 << vtype->lmul) * cpu->cfg.vlen / (8 * (1 << vtype->sew));
+    if (s1 == 0) {
+        vl = vlmax;
+    } else if (s1 <= vlmax) {
+        vl = s1;
+    } else {
+        vl = vlmax;
+    }
+    env->vext.vl = vl;
+    env->vext.vtype = s2;
+    env->vext.vstart = 0;
+    return vl;
+}