@samitouri / QOSamiQemu / commits / 66e4d3517b

target/riscv: rvv: Set mstatus.FS dirty when vector FP raises exceptions

According to the RISC-V privileged spec 3.1.6, any instruction that modifies FP extension state (FP CSRs including fflags, or f registers) must set mstatus.FS to Dirty. Raising fflags bits is modifying fcsr (an FP CSR). When a vector FP instruction raises a floating-point exception, it modifies fflags (an FP CSR), but current implementation was not marking mstatus.FS dirty in this case. Fix the issue by snapshot fflags before the element loop and OR MSTATUS_FS into env->mstatus if any new exception bits are set afterwards. Signed-off-by: Max Chou <max.chou@sifive.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260611105037.157773-3-max.chou@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Max Chou committed Jun 11, 2026 at 18:50 UTC 66e4d3517bc71d5df22803880ff5be09a0269543
1 file changed +128 -113
target/riscv/vector_helper.c
+128 -113
@@ -3172,34 +3172,36 @@ static void do_##NAME(void *vd, void *vs1, void *vs2, int i, \
3172 *((TD *)vd + HD(i)) = OP(s2, s1, &env->fp_status); \
3173 }
3174
3175 -#define GEN_VEXT_VV_ENV(NAME, ESZ) \
3176 -void HELPER(NAME)(void *vd, void *v0, void *vs1, \
3177 - void *vs2, CPURISCVState *env, \
3178 - uint32_t desc) \
3179 -{ \
3180 - uint32_t vm = vext_vm(desc); \
3181 - uint32_t vl = env->vl; \
3182 - uint32_t total_elems = \
3183 - vext_get_total_elems(env, desc, ESZ); \
3184 - uint32_t vta = vext_vta(desc); \
3185 - uint32_t vma = vext_vma(desc); \
3186 - uint32_t i; \
3187 - \
3188 - VSTART_CHECK_EARLY_EXIT(env, vl); \
3189 - \
3190 - for (i = env->vstart; i < vl; i++) { \
3191 - if (!vm && !vext_elem_mask(v0, i)) { \
3192 - /* set masked-off elements to 1s */ \
3193 - vext_set_elems_1s(vd, vma, i * ESZ, \
3194 - (i + 1) * ESZ); \
3195 - continue; \
3196 - } \
3197 - do_##NAME(vd, vs1, vs2, i, env); \
3198 - } \
3199 - env->vstart = 0; \
3200 - /* set tail elements to 1s */ \
3201 - vext_set_elems_1s(vd, vta, vl * ESZ, \
3202 - total_elems * ESZ); \
3175 +#define GEN_VEXT_VV_ENV(NAME, ESZ) \
3176 +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
3177 + CPURISCVState *env, uint32_t desc) \
3178 +{ \
3179 + uint32_t vm = vext_vm(desc); \
3180 + uint32_t vl = env->vl; \
3181 + uint32_t total_elems = \
3182 + vext_get_total_elems(env, desc, ESZ); \
3183 + uint32_t vta = vext_vta(desc); \
3184 + uint32_t vma = vext_vma(desc); \
3185 + uint32_t i; \
3186 + FloatExceptionFlags pre_fflag = \
3187 + get_float_exception_flags(&env->fp_status); \
3188 + \
3189 + VSTART_CHECK_EARLY_EXIT(env, vl); \
3190 + \
3191 + for (i = env->vstart; i < vl; i++) { \
3192 + if (!vm && !vext_elem_mask(v0, i)) { \
3193 + /* set masked-off elements to 1s */ \
3194 + vext_set_elems_1s(vd, vma, i * ESZ, \
3195 + (i + 1) * ESZ); \
3196 + continue; \
3197 + } \
3198 + do_##NAME(vd, vs1, vs2, i, env); \
3199 + } \
3200 + env->vstart = 0; \
3201 + /* set tail elements to 1s */ \
3202 + vext_set_elems_1s(vd, vta, vl * ESZ, \
3203 + total_elems * ESZ); \
3204 + riscv_cpu_check_fflags(env, pre_fflag); \
3205 }
3206
3207 RVVCALL(OPFVV2, vfadd_vv_h_bf16, OP_UUU_H, H2, H2, H2, bfloat16_add)
@@ -3219,34 +3221,36 @@ static void do_##NAME(void *vd, uint64_t s1, void *vs2, int i, \
3221 *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1, &env->fp_status);\
3222 }
3223
3222 -#define GEN_VEXT_VF(NAME, ESZ) \
3223 -void HELPER(NAME)(void *vd, void *v0, uint64_t s1, \
3224 - void *vs2, CPURISCVState *env, \
3225 - uint32_t desc) \
3226 -{ \
3227 - uint32_t vm = vext_vm(desc); \
3228 - uint32_t vl = env->vl; \
3229 - uint32_t total_elems = \
3230 - vext_get_total_elems(env, desc, ESZ); \
3231 - uint32_t vta = vext_vta(desc); \
3232 - uint32_t vma = vext_vma(desc); \
3233 - uint32_t i; \
3234 - \
3235 - VSTART_CHECK_EARLY_EXIT(env, vl); \
3236 - \
3237 - for (i = env->vstart; i < vl; i++) { \
3238 - if (!vm && !vext_elem_mask(v0, i)) { \
3239 - /* set masked-off elements to 1s */ \
3240 - vext_set_elems_1s(vd, vma, i * ESZ, \
3241 - (i + 1) * ESZ); \
3242 - continue; \
3243 - } \
3244 - do_##NAME(vd, s1, vs2, i, env); \
3245 - } \
3246 - env->vstart = 0; \
3247 - /* set tail elements to 1s */ \
3248 - vext_set_elems_1s(vd, vta, vl * ESZ, \
3249 - total_elems * ESZ); \
3224 +#define GEN_VEXT_VF(NAME, ESZ) \
3225 +void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \
3226 + CPURISCVState *env, uint32_t desc) \
3227 +{ \
3228 + uint32_t vm = vext_vm(desc); \
3229 + uint32_t vl = env->vl; \
3230 + uint32_t total_elems = \
3231 + vext_get_total_elems(env, desc, ESZ); \
3232 + uint32_t vta = vext_vta(desc); \
3233 + uint32_t vma = vext_vma(desc); \
3234 + uint32_t i; \
3235 + FloatExceptionFlags pre_fflag = \
3236 + get_float_exception_flags(&env->fp_status); \
3237 + \
3238 + VSTART_CHECK_EARLY_EXIT(env, vl); \
3239 + \
3240 + for (i = env->vstart; i < vl; i++) { \
3241 + if (!vm && !vext_elem_mask(v0, i)) { \
3242 + /* set masked-off elements to 1s */ \
3243 + vext_set_elems_1s(vd, vma, i * ESZ, \
3244 + (i + 1) * ESZ); \
3245 + continue; \
3246 + } \
3247 + do_##NAME(vd, s1, vs2, i, env); \
3248 + } \
3249 + env->vstart = 0; \
3250 + /* set tail elements to 1s */ \
3251 + vext_set_elems_1s(vd, vta, vl * ESZ, \
3252 + total_elems * ESZ); \
3253 + riscv_cpu_check_fflags(env, pre_fflag); \
3254 }
3255
3256 RVVCALL(OPFVF2, vfadd_vf_h_bf16, OP_UUU_H, H2, H2, bfloat16_add)
@@ -3993,35 +3997,38 @@ static void do_##NAME(void *vd, void *vs2, int i, \
3997 *((TD *)vd + HD(i)) = OP(s2, &env->fp_status); \
3998 }
3999
3996 -#define GEN_VEXT_V_ENV(NAME, ESZ) \
3997 -void HELPER(NAME)(void *vd, void *v0, void *vs2, \
3998 - CPURISCVState *env, uint32_t desc) \
3999 -{ \
4000 - uint32_t vm = vext_vm(desc); \
4001 - uint32_t vl = env->vl; \
4002 - uint32_t total_elems = \
4003 - vext_get_total_elems(env, desc, ESZ); \
4004 - uint32_t vta = vext_vta(desc); \
4005 - uint32_t vma = vext_vma(desc); \
4006 - uint32_t i; \
4007 - \
4008 - VSTART_CHECK_EARLY_EXIT(env, vl); \
4009 - \
4010 - if (vl == 0) { \
4011 - return; \
4012 - } \
4013 - for (i = env->vstart; i < vl; i++) { \
4014 - if (!vm && !vext_elem_mask(v0, i)) { \
4015 - /* set masked-off elements to 1s */ \
4016 - vext_set_elems_1s(vd, vma, i * ESZ, \
4017 - (i + 1) * ESZ); \
4018 - continue; \
4019 - } \
4020 - do_##NAME(vd, vs2, i, env); \
4021 - } \
4022 - env->vstart = 0; \
4023 - vext_set_elems_1s(vd, vta, vl * ESZ, \
4024 - total_elems * ESZ); \
4000 +#define GEN_VEXT_V_ENV(NAME, ESZ) \
4001 +void HELPER(NAME)(void *vd, void *v0, void *vs2, \
4002 + CPURISCVState *env, uint32_t desc) \
4003 +{ \
4004 + uint32_t vm = vext_vm(desc); \
4005 + uint32_t vl = env->vl; \
4006 + uint32_t total_elems = \
4007 + vext_get_total_elems(env, desc, ESZ); \
4008 + uint32_t vta = vext_vta(desc); \
4009 + uint32_t vma = vext_vma(desc); \
4010 + uint32_t i; \
4011 + FloatExceptionFlags pre_fflag = \
4012 + get_float_exception_flags(&env->fp_status); \
4013 + \
4014 + VSTART_CHECK_EARLY_EXIT(env, vl); \
4015 + \
4016 + if (vl == 0) { \
4017 + return; \
4018 + } \
4019 + for (i = env->vstart; i < vl; i++) { \
4020 + if (!vm && !vext_elem_mask(v0, i)) { \
4021 + /* set masked-off elements to 1s */ \
4022 + vext_set_elems_1s(vd, vma, i * ESZ, \
4023 + (i + 1) * ESZ); \
4024 + continue; \
4025 + } \
4026 + do_##NAME(vd, vs2, i, env); \
4027 + } \
4028 + env->vstart = 0; \
4029 + vext_set_elems_1s(vd, vta, vl * ESZ, \
4030 + total_elems * ESZ); \
4031 + riscv_cpu_check_fflags(env, pre_fflag); \
4032 }
4033
4034 RVVCALL(OPFVV1, vfsqrt_v_h, OP_UU_H, H2, H2, float16_sqrt)
@@ -4610,6 +4617,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
4617 uint32_t vta_all_1s = vext_vta_all_1s(desc); \
4618 uint32_t vma = vext_vma(desc); \
4619 uint32_t i; \
4620 + FloatExceptionFlags pre_fflag = \
4621 + get_float_exception_flags(&env->fp_status); \
4622 \
4623 VSTART_CHECK_EARLY_EXIT(env, vl); \
4624 \
@@ -4636,6 +4645,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
4645 vext_set_elem_mask(vd, i, 1); \
4646 } \
4647 } \
4648 + riscv_cpu_check_fflags(env, pre_fflag); \
4649 }
4650
4651 GEN_VEXT_CMP_VV_ENV(vmfeq_vv_h_bf16, uint16_t, H2, bfloat16_eq_quiet)
@@ -4653,6 +4663,8 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \
4663 uint32_t vta_all_1s = vext_vta_all_1s(desc); \
4664 uint32_t vma = vext_vma(desc); \
4665 uint32_t i; \
4666 + FloatExceptionFlags pre_fflag = \
4667 + get_float_exception_flags(&env->fp_status); \
4668 \
4669 VSTART_CHECK_EARLY_EXIT(env, vl); \
4670 \
@@ -4678,6 +4690,7 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \
4690 vext_set_elem_mask(vd, i, 1); \
4691 } \
4692 } \
4693 + riscv_cpu_check_fflags(env, pre_fflag); \
4694 }
4695
4696 GEN_VEXT_CMP_VF(vmfeq_vf_h_bf16, uint16_t, H2, bfloat16_eq_quiet)
@@ -5151,34 +5164,36 @@ GEN_VEXT_RED(vwredsumu_vs_h, uint32_t, uint16_t, H4, H2, DO_ADD)
5164 GEN_VEXT_RED(vwredsumu_vs_w, uint64_t, uint32_t, H8, H4, DO_ADD)
5165
5166 /* Vector Single-Width Floating-Point Reduction Instructions */
5154 -#define GEN_VEXT_FRED(NAME, TD, TS2, HD, HS2, OP) \
5155 -void HELPER(NAME)(void *vd, void *v0, void *vs1, \
5156 - void *vs2, CPURISCVState *env, \
5157 - uint32_t desc) \
5158 -{ \
5159 - uint32_t vm = vext_vm(desc); \
5160 - uint32_t vl = env->vl; \
5161 - uint32_t esz = sizeof(TD); \
5162 - uint32_t vlenb = simd_maxsz(desc); \
5163 - uint32_t vta = vext_vta(desc); \
5164 - uint32_t i; \
5165 - TD s1 = *((TD *)vs1 + HD(0)); \
5166 - \
5167 - VSTART_CHECK_EARLY_EXIT(env, vl); \
5168 - \
5169 - for (i = env->vstart; i < vl; i++) { \
5170 - TS2 s2 = *((TS2 *)vs2 + HS2(i)); \
5171 - if (!vm && !vext_elem_mask(v0, i)) { \
5172 - continue; \
5173 - } \
5174 - s1 = OP(s1, (TD)s2, &env->fp_status); \
5175 - } \
5176 - if (vl > 0) { \
5177 - *((TD *)vd + HD(0)) = s1; \
5178 - } \
5179 - env->vstart = 0; \
5180 - /* set tail elements to 1s */ \
5181 - vext_set_elems_1s(vd, vta, esz, vlenb); \
5167 +#define GEN_VEXT_FRED(NAME, TD, TS2, HD, HS2, OP) \
5168 +void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
5169 + CPURISCVState *env, uint32_t desc) \
5170 +{ \
5171 + uint32_t vm = vext_vm(desc); \
5172 + uint32_t vl = env->vl; \
5173 + uint32_t esz = sizeof(TD); \
5174 + uint32_t vlenb = simd_maxsz(desc); \
5175 + uint32_t vta = vext_vta(desc); \
5176 + uint32_t i; \
5177 + FloatExceptionFlags pre_fflag = \
5178 + get_float_exception_flags(&env->fp_status); \
5179 + TD s1 = *((TD *)vs1 + HD(0)); \
5180 + \
5181 + VSTART_CHECK_EARLY_EXIT(env, vl); \
5182 + \
5183 + for (i = env->vstart; i < vl; i++) { \
5184 + TS2 s2 = *((TS2 *)vs2 + HS2(i)); \
5185 + if (!vm && !vext_elem_mask(v0, i)) { \
5186 + continue; \
5187 + } \
5188 + s1 = OP(s1, (TD)s2, &env->fp_status); \
5189 + } \
5190 + if (vl > 0) { \
5191 + *((TD *)vd + HD(0)) = s1; \
5192 + } \
5193 + env->vstart = 0; \
5194 + /* set tail elements to 1s */ \
5195 + vext_set_elems_1s(vd, vta, esz, vlenb); \
5196 + riscv_cpu_check_fflags(env, pre_fflag); \
5197 }
5198
5199 /* Unordered sum */