@@ -35,45 +35,41 @@ struct target_mcontext {
35
35
target_ulong mc_gregs [48 ];
36
36
/* Includes fpscr. */
37
37
uint64_t mc_fregs [33 ];
38
+
38
39
#if defined(TARGET_PPC64 )
39
40
/* Pointer to the vector regs */
40
41
target_ulong v_regs ;
42
+ /*
43
+ * On ppc64, this mcontext structure is naturally *unaligned*,
44
+ * or rather it is aligned on a 8 bytes boundary but not on
45
+ * a 16 byte boundary. This pad fixes it up. This is why we
46
+ * cannot use ppc_avr_t, which would force alignment. This is
47
+ * also why the vector regs are referenced in the ABI by the
48
+ * v_regs pointer above so any amount of padding can be added here.
49
+ */
50
+ target_ulong pad ;
51
+ /* VSCR and VRSAVE are saved separately. Also reserve space for VSX. */
52
+ struct {
53
+ uint64_t altivec [34 + 16 ][2 ];
54
+ } mc_vregs ;
41
55
#else
42
56
target_ulong mc_pad [2 ];
43
- #endif
57
+
44
58
/* We need to handle Altivec and SPE at the same time, which no
45
59
kernel needs to do. Fortunately, the kernel defines this bit to
46
60
be Altivec-register-large all the time, rather than trying to
47
61
twiddle it based on the specific platform. */
48
62
union {
49
63
/* SPE vector registers. One extra for SPEFSCR. */
50
64
uint32_t spe [33 ];
51
- /* Altivec vector registers. The packing of VSCR and VRSAVE
52
- varies depending on whether we're PPC64 or not: PPC64 splits
53
- them apart; PPC32 stuffs them together.
54
- We also need to account for the VSX registers on PPC64
55
- */
56
- #if defined(TARGET_PPC64 )
57
- #define QEMU_NVRREG (34 + 16)
58
- /* On ppc64, this mcontext structure is naturally *unaligned*,
59
- * or rather it is aligned on a 8 bytes boundary but not on
60
- * a 16 bytes one. This pad fixes it up. This is also why the
61
- * vector regs are referenced by the v_regs pointer above so
62
- * any amount of padding can be added here
63
- */
64
- target_ulong pad ;
65
- #else
66
- /* On ppc32, we are already aligned to 16 bytes */
67
- #define QEMU_NVRREG 33
68
- #endif
69
- /* We cannot use ppc_avr_t here as we do *not* want the implied
70
- * 16-bytes alignment that would result from it. This would have
71
- * the effect of making the whole struct target_mcontext aligned
72
- * which breaks the layout of struct target_ucontext on ppc64.
65
+ /*
66
+ * Altivec vector registers. One extra for VRSAVE.
67
+ * On ppc32, we are already aligned to 16 bytes. We could
68
+ * use ppc_avr_t, but choose to share the same type as ppc64.
73
69
*/
74
- uint64_t altivec [QEMU_NVRREG ][2 ];
75
- #undef QEMU_NVRREG
70
+ uint64_t altivec [33 ][2 ];
76
71
} mc_vregs ;
72
+ #endif
77
73
};
78
74
79
75
/* See arch/powerpc/include/asm/sigcontext.h. */
@@ -278,6 +274,7 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
278
274
__put_user ((uint32_t )env -> spr [SPR_VRSAVE ], vrsave );
279
275
}
280
276
277
+ #if defined(TARGET_PPC64 )
281
278
/* Save VSX second halves */
282
279
if (env -> insns_flags2 & PPC2_VSX ) {
283
280
uint64_t * vsregs = (uint64_t * )& frame -> mc_vregs .altivec [34 ];
@@ -286,6 +283,7 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
286
283
__put_user (* vsrl , & vsregs [i ]);
287
284
}
288
285
}
286
+ #endif
289
287
290
288
/* Save floating point registers. */
291
289
if (env -> insns_flags & PPC_FLOAT ) {
@@ -296,22 +294,18 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
296
294
__put_user ((uint64_t ) env -> fpscr , & frame -> mc_fregs [32 ]);
297
295
}
298
296
297
+ #if !defined(TARGET_PPC64 )
299
298
/* Save SPE registers. The kernel only saves the high half. */
300
299
if (env -> insns_flags & PPC_SPE ) {
301
- #if defined(TARGET_PPC64 )
302
- for (i = 0 ; i < ARRAY_SIZE (env -> gpr ); i ++ ) {
303
- __put_user (env -> gpr [i ] >> 32 , & frame -> mc_vregs .spe [i ]);
304
- }
305
- #else
306
300
for (i = 0 ; i < ARRAY_SIZE (env -> gprh ); i ++ ) {
307
301
__put_user (env -> gprh [i ], & frame -> mc_vregs .spe [i ]);
308
302
}
309
- #endif
310
303
/* Set MSR_SPE in the saved MSR value to indicate that
311
304
frame->mc_vregs contains valid data. */
312
305
msr |= MSR_SPE ;
313
306
__put_user (env -> spe_fscr , & frame -> mc_vregs .spe [32 ]);
314
307
}
308
+ #endif
315
309
316
310
/* Store MSR. */
317
311
__put_user (msr , & frame -> mc_gregs [TARGET_PT_MSR ]);
@@ -392,6 +386,7 @@ static void restore_user_regs(CPUPPCState *env,
392
386
__get_user (env -> spr [SPR_VRSAVE ], vrsave );
393
387
}
394
388
389
+ #if defined(TARGET_PPC64 )
395
390
/* Restore VSX second halves */
396
391
if (env -> insns_flags2 & PPC2_VSX ) {
397
392
uint64_t * vsregs = (uint64_t * )& frame -> mc_vregs .altivec [34 ];
@@ -400,6 +395,7 @@ static void restore_user_regs(CPUPPCState *env,
400
395
__get_user (* vsrl , & vsregs [i ]);
401
396
}
402
397
}
398
+ #endif
403
399
404
400
/* Restore floating point registers. */
405
401
if (env -> insns_flags & PPC_FLOAT ) {
@@ -412,22 +408,15 @@ static void restore_user_regs(CPUPPCState *env,
412
408
env -> fpscr = (uint32_t ) fpscr ;
413
409
}
414
410
411
+ #if !defined(TARGET_PPC64 )
415
412
/* Save SPE registers. The kernel only saves the high half. */
416
413
if (env -> insns_flags & PPC_SPE ) {
417
- #if defined(TARGET_PPC64 )
418
- for (i = 0 ; i < ARRAY_SIZE (env -> gpr ); i ++ ) {
419
- uint32_t hi ;
420
-
421
- __get_user (hi , & frame -> mc_vregs .spe [i ]);
422
- env -> gpr [i ] = ((uint64_t )hi << 32 ) | ((uint32_t ) env -> gpr [i ]);
423
- }
424
- #else
425
414
for (i = 0 ; i < ARRAY_SIZE (env -> gprh ); i ++ ) {
426
415
__get_user (env -> gprh [i ], & frame -> mc_vregs .spe [i ]);
427
416
}
428
- #endif
429
417
__get_user (env -> spe_fscr , & frame -> mc_vregs .spe [32 ]);
430
418
}
419
+ #endif
431
420
}
432
421
433
422
#if !defined(TARGET_PPC64 )
0 commit comments