@@ -41,6 +41,13 @@ void cpu_loop(CPURISCVState *env)
sigcode = 0;
sigaddr = 0;
+ if (env->foflag) {
+ if (env->vfp.vl != 0) {
+ env->foflag = false;
+ env->pc += 4;
+ continue;
+ }
+ }
switch (trapnr) {
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
@@ -521,6 +521,13 @@ void riscv_cpu_do_interrupt(CPUState *cs)
[PRV_H] = RISCV_EXCP_H_ECALL,
[PRV_M] = RISCV_EXCP_M_ECALL
};
+ if (env->foflag) {
+ if (env->vfp.vl != 0) {
+ env->foflag = false;
+ env->pc += 4;
+ return;
+ }
+ }
if (!async) {
/* set tval to badaddr for traps with address information */
@@ -84,6 +84,13 @@ DEF_HELPER_5(vector_vle_v, void, env, i32, i32, i32, i32)
DEF_HELPER_5(vector_vlbu_v, void, env, i32, i32, i32, i32)
DEF_HELPER_5(vector_vlhu_v, void, env, i32, i32, i32, i32)
DEF_HELPER_5(vector_vlwu_v, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vector_vlbff_v, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vector_vlhff_v, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vector_vlwff_v, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vector_vleff_v, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vector_vlbuff_v, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vector_vlhuff_v, void, env, i32, i32, i32, i32)
+DEF_HELPER_5(vector_vlwuff_v, void, env, i32, i32, i32, i32)
DEF_HELPER_5(vector_vsb_v, void, env, i32, i32, i32, i32)
DEF_HELPER_5(vector_vsh_v, void, env, i32, i32, i32, i32)
DEF_HELPER_5(vector_vsw_v, void, env, i32, i32, i32, i32)
@@ -218,6 +218,13 @@ vle_v ... 000 . 00000 ..... 111 ..... 0000111 @r2_nfvm
vlbu_v ... 000 . 00000 ..... 000 ..... 0000111 @r2_nfvm
vlhu_v ... 000 . 00000 ..... 101 ..... 0000111 @r2_nfvm
vlwu_v ... 000 . 00000 ..... 110 ..... 0000111 @r2_nfvm
+vlbff_v ... 100 . 10000 ..... 000 ..... 0000111 @r2_nfvm
+vlhff_v ... 100 . 10000 ..... 101 ..... 0000111 @r2_nfvm
+vlwff_v ... 100 . 10000 ..... 110 ..... 0000111 @r2_nfvm
+vleff_v ... 000 . 10000 ..... 111 ..... 0000111 @r2_nfvm
+vlbuff_v ... 000 . 10000 ..... 000 ..... 0000111 @r2_nfvm
+vlhuff_v ... 000 . 10000 ..... 101 ..... 0000111 @r2_nfvm
+vlwuff_v ... 000 . 10000 ..... 110 ..... 0000111 @r2_nfvm
vsb_v ... 000 . 00000 ..... 000 ..... 0100111 @r2_nfvm
vsh_v ... 000 . 00000 ..... 101 ..... 0100111 @r2_nfvm
vsw_v ... 000 . 00000 ..... 110 ..... 0100111 @r2_nfvm
@@ -80,6 +80,13 @@ GEN_VECTOR_R2_NFVM(vle_v)
GEN_VECTOR_R2_NFVM(vlbu_v)
GEN_VECTOR_R2_NFVM(vlhu_v)
GEN_VECTOR_R2_NFVM(vlwu_v)
+GEN_VECTOR_R2_NFVM(vlbff_v)
+GEN_VECTOR_R2_NFVM(vlhff_v)
+GEN_VECTOR_R2_NFVM(vlwff_v)
+GEN_VECTOR_R2_NFVM(vleff_v)
+GEN_VECTOR_R2_NFVM(vlbuff_v)
+GEN_VECTOR_R2_NFVM(vlhuff_v)
+GEN_VECTOR_R2_NFVM(vlwuff_v)
GEN_VECTOR_R2_NFVM(vsb_v)
GEN_VECTOR_R2_NFVM(vsh_v)
GEN_VECTOR_R2_NFVM(vsw_v)
@@ -2762,3 +2762,570 @@ void VECTOR_HELPER(vsuxe_v)(CPURISCVState *env, uint32_t nf, uint32_t vm,
env->vfp.vstart = 0;
}
+void VECTOR_HELPER(vlbuff_v)(CPURISCVState *env, uint32_t nf, uint32_t vm,
+ uint32_t rs1, uint32_t rd)
+{
+ int i, j, k, vl, vlmax, lmul, width, dest, read;
+
+ vl = env->vfp.vl;
+
+ lmul = vector_get_lmul(env);
+ width = vector_get_width(env);
+ vlmax = vector_get_vlmax(env);
+
+ if (vector_vtype_ill(env) || vector_overlap_vm_common(lmul, vm, rd)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ if (lmul * (nf + 1) > 32) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+
+ vector_lmul_check_reg(env, lmul, rd, false);
+
+ env->foflag = true;
+ env->vfp.vl = 0;
+ for (i = 0; i < vlmax; i++) {
+ dest = rd + (i / (VLEN / width));
+ j = i % (VLEN / width);
+ k = nf;
+ if (i < env->vfp.vstart) {
+ continue;
+ } else if (i < vl) {
+ switch (width) {
+ case 8:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = i * (nf + 1) + k;
+ env->vfp.vreg[dest + k * lmul].u8[j] =
+ cpu_ldub_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 16:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = i * (nf + 1) + k;
+ env->vfp.vreg[dest + k * lmul].u16[j] =
+ cpu_ldub_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 32:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = i * (nf + 1) + k;
+ env->vfp.vreg[dest + k * lmul].u32[j] =
+ cpu_ldub_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 64:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = i * (nf + 1) + k;
+ env->vfp.vreg[dest + k * lmul].u64[j] =
+ cpu_ldub_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ default:
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ } else {
+ vector_tail_segment(env, dest, j, width, k, lmul);
+ }
+ }
+ env->foflag = false;
+ env->vfp.vl = vl;
+ env->vfp.vstart = 0;
+}
+
+void VECTOR_HELPER(vlbff_v)(CPURISCVState *env, uint32_t nf, uint32_t vm,
+ uint32_t rs1, uint32_t rd)
+{
+ int i, j, k, vl, vlmax, lmul, width, dest, read;
+
+ vl = env->vfp.vl;
+
+ lmul = vector_get_lmul(env);
+ width = vector_get_width(env);
+ vlmax = vector_get_vlmax(env);
+
+ if (vector_vtype_ill(env) || vector_overlap_vm_common(lmul, vm, rd)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ if (lmul * (nf + 1) > 32) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+
+ vector_lmul_check_reg(env, lmul, rd, false);
+ env->foflag = true;
+ env->vfp.vl = 0;
+ for (i = 0; i < vlmax; i++) {
+ dest = rd + (i / (VLEN / width));
+ j = i % (VLEN / width);
+ k = nf;
+ if (i < env->vfp.vstart) {
+ continue;
+ } else if (i < vl) {
+ switch (width) {
+ case 8:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = i * (nf + 1) + k;
+ env->vfp.vreg[dest + k * lmul].s8[j] =
+ cpu_ldsb_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 16:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = i * (nf + 1) + k;
+ env->vfp.vreg[dest + k * lmul].s16[j] = sign_extend(
+ cpu_ldsb_data(env, env->gpr[rs1] + read), 8);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 32:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = i * (nf + 1) + k;
+ env->vfp.vreg[dest + k * lmul].s32[j] = sign_extend(
+ cpu_ldsb_data(env, env->gpr[rs1] + read), 8);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 64:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = i * (nf + 1) + k;
+ env->vfp.vreg[dest + k * lmul].s64[j] = sign_extend(
+ cpu_ldsb_data(env, env->gpr[rs1] + read), 8);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ default:
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ } else {
+ vector_tail_segment(env, dest, j, width, k, lmul);
+ }
+ }
+ env->foflag = false;
+ env->vfp.vl = vl;
+ env->vfp.vstart = 0;
+}
+
+void VECTOR_HELPER(vlhuff_v)(CPURISCVState *env, uint32_t nf, uint32_t vm,
+ uint32_t rs1, uint32_t rd)
+{
+ int i, j, k, vl, vlmax, lmul, width, dest, read;
+
+ vl = env->vfp.vl;
+
+ lmul = vector_get_lmul(env);
+ width = vector_get_width(env);
+ vlmax = vector_get_vlmax(env);
+
+ if (vector_vtype_ill(env) || vector_overlap_vm_common(lmul, vm, rd)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ if (lmul * (nf + 1) > 32) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ vector_lmul_check_reg(env, lmul, rd, false);
+ env->foflag = true;
+ env->vfp.vl = 0;
+ for (i = 0; i < vlmax; i++) {
+ dest = rd + (i / (VLEN / width));
+ j = i % (VLEN / width);
+ k = nf;
+ if (i < env->vfp.vstart) {
+ continue;
+ } else if (i < vl) {
+ switch (width) {
+ case 16:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 2;
+ env->vfp.vreg[dest + k * lmul].u16[j] =
+ cpu_lduw_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 32:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 2;
+ env->vfp.vreg[dest + k * lmul].u32[j] =
+ cpu_lduw_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 64:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 2;
+ env->vfp.vreg[dest + k * lmul].u64[j] =
+ cpu_lduw_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ default:
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ } else {
+ vector_tail_segment(env, dest, j, width, k, lmul);
+ }
+ }
+ env->foflag = false;
+ env->vfp.vl = vl;
+ env->vfp.vstart = 0;
+}
+
+void VECTOR_HELPER(vlhff_v)(CPURISCVState *env, uint32_t nf, uint32_t vm,
+ uint32_t rs1, uint32_t rd)
+{
+ int i, j, k, vl, vlmax, lmul, width, dest, read;
+
+ vl = env->vfp.vl;
+
+ lmul = vector_get_lmul(env);
+ width = vector_get_width(env);
+ vlmax = vector_get_vlmax(env);
+
+ if (vector_vtype_ill(env) || vector_overlap_vm_common(lmul, vm, rd)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ if (lmul * (nf + 1) > 32) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ vector_lmul_check_reg(env, lmul, rd, false);
+ env->foflag = true;
+ env->vfp.vl = 0;
+ for (i = 0; i < vlmax; i++) {
+ dest = rd + (i / (VLEN / width));
+ j = i % (VLEN / width);
+ k = nf;
+ if (i < env->vfp.vstart) {
+ continue;
+ } else if (i < vl) {
+ switch (width) {
+ case 16:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 2;
+ env->vfp.vreg[dest + k * lmul].s16[j] =
+ cpu_ldsw_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 32:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 2;
+ env->vfp.vreg[dest + k * lmul].s32[j] = sign_extend(
+ cpu_ldsw_data(env, env->gpr[rs1] + read), 16);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 64:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 2;
+ env->vfp.vreg[dest + k * lmul].s64[j] = sign_extend(
+ cpu_ldsw_data(env, env->gpr[rs1] + read), 16);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ default:
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ } else {
+ vector_tail_segment(env, dest, j, width, k, lmul);
+ }
+ }
+ env->vfp.vl = vl;
+ env->foflag = false;
+ env->vfp.vstart = 0;
+}
+
+void VECTOR_HELPER(vlwuff_v)(CPURISCVState *env, uint32_t nf, uint32_t vm,
+ uint32_t rs1, uint32_t rd)
+{
+ int i, j, k, vl, vlmax, lmul, width, dest, read;
+
+ vl = env->vfp.vl;
+
+ lmul = vector_get_lmul(env);
+ width = vector_get_width(env);
+ vlmax = vector_get_vlmax(env);
+
+ if (vector_vtype_ill(env) || vector_overlap_vm_common(lmul, vm, rd)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ if (lmul * (nf + 1) > 32) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ vector_lmul_check_reg(env, lmul, rd, false);
+ env->foflag = true;
+ env->vfp.vl = 0;
+ for (i = 0; i < vlmax; i++) {
+ dest = rd + (i / (VLEN / width));
+ j = i % (VLEN / width);
+ k = nf;
+ if (i < env->vfp.vstart) {
+ continue;
+ } else if (i < vl) {
+ switch (width) {
+ case 32:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 4;
+ env->vfp.vreg[dest + k * lmul].u32[j] =
+ cpu_ldl_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 64:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 4;
+ env->vfp.vreg[dest + k * lmul].u64[j] =
+ cpu_ldl_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ default:
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ } else {
+ vector_tail_segment(env, dest, j, width, k, lmul);
+ }
+ }
+ env->foflag = false;
+ env->vfp.vl = vl;
+ env->vfp.vstart = 0;
+}
+
+void VECTOR_HELPER(vlwff_v)(CPURISCVState *env, uint32_t nf, uint32_t vm,
+ uint32_t rs1, uint32_t rd)
+{
+ int i, j, k, vl, vlmax, lmul, width, dest, read;
+
+ vl = env->vfp.vl;
+
+ lmul = vector_get_lmul(env);
+ width = vector_get_width(env);
+ vlmax = vector_get_vlmax(env);
+
+ if (vector_vtype_ill(env) || vector_overlap_vm_common(lmul, vm, rd)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ if (lmul * (nf + 1) > 32) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ vector_lmul_check_reg(env, lmul, rd, false);
+ env->foflag = true;
+ env->vfp.vl = 0;
+ for (i = 0; i < vlmax; i++) {
+ dest = rd + (i / (VLEN / width));
+ j = i % (VLEN / width);
+ k = nf;
+ if (i < env->vfp.vstart) {
+ continue;
+ } else if (i < vl) {
+ switch (width) {
+ case 32:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 4;
+ env->vfp.vreg[dest + k * lmul].s32[j] =
+ cpu_ldl_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 64:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 4;
+ env->vfp.vreg[dest + k * lmul].s64[j] = sign_extend(
+ cpu_ldl_data(env, env->gpr[rs1] + read), 32);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ default:
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ } else {
+ vector_tail_segment(env, dest, j, width, k, lmul);
+ }
+ }
+ env->foflag = false;
+ env->vfp.vl = vl;
+ env->vfp.vstart = 0;
+}
+
+void VECTOR_HELPER(vleff_v)(CPURISCVState *env, uint32_t nf, uint32_t vm,
+ uint32_t rs1, uint32_t rd)
+{
+ int i, j, k, vl, vlmax, lmul, width, dest, read;
+
+ vl = env->vfp.vl;
+ lmul = vector_get_lmul(env);
+ width = vector_get_width(env);
+ vlmax = vector_get_vlmax(env);
+
+ if (vector_vtype_ill(env) || vector_overlap_vm_common(lmul, vm, rd)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ if (lmul * (nf + 1) > 32) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+
+ vector_lmul_check_reg(env, lmul, rd, false);
+ env->vfp.vl = 0;
+ env->foflag = true;
+ for (i = 0; i < vlmax; i++) {
+ dest = rd + (i / (VLEN / width));
+ j = i % (VLEN / width);
+ k = nf;
+ if (i < env->vfp.vstart) {
+ continue;
+ } else if (i < vl) {
+ switch (width) {
+ case 8:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = i * (nf + 1) + k;
+ env->vfp.vreg[dest + k * lmul].u8[j] =
+ cpu_ldub_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 16:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 2;
+ env->vfp.vreg[dest + k * lmul].u16[j] =
+ cpu_lduw_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 32:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 4;
+ env->vfp.vreg[dest + k * lmul].u32[j] =
+ cpu_ldl_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ case 64:
+ if (vector_elem_mask(env, vm, width, lmul, i)) {
+ while (k >= 0) {
+ read = (i * (nf + 1) + k) * 8;
+ env->vfp.vreg[dest + k * lmul].u64[j] =
+ cpu_ldq_data(env, env->gpr[rs1] + read);
+ k--;
+ }
+ env->vfp.vstart++;
+ }
+ env->vfp.vl++;
+ break;
+ default:
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ return;
+ }
+ } else {
+ vector_tail_segment(env, dest, j, width, k, lmul);
+ }
+ }
+ env->foflag = false;
+ env->vfp.vl = vl;
+ env->vfp.vstart = 0;
+}