@@ -113,11 +113,12 @@ static void vfp_set_fpsr_to_host(CPUARMState *env, uint32_t val)
113
113
set_float_exception_flags (0 , & env -> vfp .standard_fp_status_f16 );
114
114
}
115
115
116
- static void vfp_set_fpcr_to_host (CPUARMState * env , uint32_t val )
116
+ static void vfp_set_fpcr_to_host (CPUARMState * env , uint32_t val , uint32_t mask )
117
117
{
118
118
uint64_t changed = env -> vfp .fpcr ;
119
119
120
120
changed ^= val ;
121
+ changed &= mask ;
121
122
if (changed & (3 << 22 )) {
122
123
int i = (val >> 22 ) & 3 ;
123
124
switch (i ) {
@@ -167,7 +168,7 @@ static void vfp_set_fpsr_to_host(CPUARMState *env, uint32_t val)
167
168
{
168
169
}
169
170
170
- static void vfp_set_fpcr_to_host (CPUARMState * env , uint32_t val )
171
+ static void vfp_set_fpcr_to_host (CPUARMState * env , uint32_t val , uint32_t mask )
171
172
{
172
173
}
173
174
@@ -239,31 +240,38 @@ void vfp_set_fpsr(CPUARMState *env, uint32_t val)
239
240
env -> vfp .fpsr = val ;
240
241
}
241
242
242
- void vfp_set_fpcr (CPUARMState * env , uint32_t val )
243
+ static void vfp_set_fpcr_masked (CPUARMState * env , uint32_t val , uint32_t mask )
243
244
{
245
+ /*
246
+ * We only set FPCR bits defined by mask, and leave the others alone.
247
+ * We assume the mask is sensible (e.g. doesn't try to set only
248
+ * part of a field)
249
+ */
244
250
ARMCPU * cpu = env_archcpu (env );
245
251
246
252
/* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
247
253
if (!cpu_isar_feature (any_fp16 , cpu )) {
248
254
val &= ~FPCR_FZ16 ;
249
255
}
250
256
251
- vfp_set_fpcr_to_host (env , val );
252
-
253
- if (!arm_feature (env , ARM_FEATURE_M )) {
254
- /*
255
- * Short-vector length and stride; on M-profile these bits
256
- * are used for different purposes.
257
- * We can't make this conditional be "if MVFR0.FPShVec != 0",
258
- * because in v7A no-short-vector-support cores still had to
259
- * allow Stride/Len to be written with the only effect that
260
- * some insns are required to UNDEF if the guest sets them.
261
- */
262
- env -> vfp .vec_len = extract32 (val , 16 , 3 );
263
- env -> vfp .vec_stride = extract32 (val , 20 , 2 );
264
- } else if (cpu_isar_feature (aa32_mve , cpu )) {
265
- env -> v7m .ltpsize = extract32 (val , FPCR_LTPSIZE_SHIFT ,
266
- FPCR_LTPSIZE_LENGTH );
257
+ vfp_set_fpcr_to_host (env , val , mask );
258
+
259
+ if (mask & (FPCR_LEN_MASK | FPCR_STRIDE_MASK )) {
260
+ if (!arm_feature (env , ARM_FEATURE_M )) {
261
+ /*
262
+ * Short-vector length and stride; on M-profile these bits
263
+ * are used for different purposes.
264
+ * We can't make this conditional be "if MVFR0.FPShVec != 0",
265
+ * because in v7A no-short-vector-support cores still had to
266
+ * allow Stride/Len to be written with the only effect that
267
+ * some insns are required to UNDEF if the guest sets them.
268
+ */
269
+ env -> vfp .vec_len = extract32 (val , 16 , 3 );
270
+ env -> vfp .vec_stride = extract32 (val , 20 , 2 );
271
+ } else if (cpu_isar_feature (aa32_mve , cpu )) {
272
+ env -> v7m .ltpsize = extract32 (val , FPCR_LTPSIZE_SHIFT ,
273
+ FPCR_LTPSIZE_LENGTH );
274
+ }
267
275
}
268
276
269
277
/*
@@ -276,12 +284,18 @@ void vfp_set_fpcr(CPUARMState *env, uint32_t val)
276
284
* bits.
277
285
*/
278
286
val &= FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK | FPCR_FZ16 ;
279
- env -> vfp .fpcr = val ;
287
+ env -> vfp .fpcr &= ~mask ;
288
+ env -> vfp .fpcr |= val ;
289
+ }
290
+
291
+ void vfp_set_fpcr (CPUARMState * env , uint32_t val )
292
+ {
293
+ vfp_set_fpcr_masked (env , val , MAKE_64BIT_MASK (0 , 32 ));
280
294
}
281
295
282
296
void HELPER (vfp_set_fpscr )(CPUARMState * env , uint32_t val )
283
297
{
284
- vfp_set_fpcr (env , val & FPSCR_FPCR_MASK );
298
+ vfp_set_fpcr_masked (env , val , FPSCR_FPCR_MASK );
285
299
vfp_set_fpsr (env , val & FPSCR_FPSR_MASK );
286
300
}
287
301
0 commit comments