powerpc: Add support for VRSAVE

The VRSAVE feature of the Altivec unit can be used to reduce the amount of
Altivec registers which need to be saved/restored during interrupt processing
and context switches.

In order to use the VRSAVE optimization a corresponding multilib (-mvrsave) is
required, see GCC configuration.  The -mvrsave option must be added to the
ABI_FLAGS of the BSP.

Currently only the -mcpu=e6500 based QorIQ BSP support this optimization.

Update #4712.
This commit is contained in:
Sebastian Huber
2020-11-02 13:02:20 +01:00
parent 85d482f122
commit d907c2294a
5 changed files with 429 additions and 23 deletions

View File

@@ -23,7 +23,7 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
* Copyright (c) 2011, 2017 embedded brains GmbH
* Copyright (c) 2011, 2020 embedded brains GmbH
*
* The license and distribution terms for this file may in
* the file LICENSE in this distribution or at
@@ -267,6 +267,10 @@ PROC (_CPU_Context_switch_no_return):
isync
#endif
#if defined(PPC_MULTILIB_ALTIVEC) && defined(__PPC_VRSAVE__)
mfvrsave r9
#endif
/* Align to a cache line */
CLEAR_RIGHT_IMMEDIATE r3, r3, PPC_DEFAULT_CACHE_LINE_POWER
CLEAR_RIGHT_IMMEDIATE r5, r4, PPC_DEFAULT_CACHE_LINE_POWER
@@ -284,6 +288,14 @@ PROC (_CPU_Context_switch_no_return):
mfmsr r6
#endif /* END PPC_DISABLE_MSR_ACCESS */
mfcr r7
#ifdef PPC_MULTILIB_ALTIVEC
#ifdef __PPC_VRSAVE__
/* Mark v0 as used since we need it to get the VSCR */
oris r8, r9, 0x8000
mtvrsave r8
#endif
mfvscr v0
#endif
mflr r8
lwz r11, PER_CPU_ISR_DISPATCH_DISABLE(r12)
@@ -356,6 +368,16 @@ PROC (_CPU_Context_switch_no_return):
stw r11, PPC_CONTEXT_OFFSET_ISR_DISPATCH_DISABLE(r3)
#ifdef PPC_MULTILIB_ALTIVEC
li r10, PPC_CONTEXT_OFFSET_VSCR
stvewx v0, r3, r10
#ifdef __PPC_VRSAVE__
stw r9, PPC_CONTEXT_OFFSET_VRSAVE(r3)
andi. r9, r9, 0xfff
bne .Laltivec_save
.Laltivec_save_continue:
#else /* __PPC_VRSAVE__ */
li r9, PPC_CONTEXT_OFFSET_V20
stvx v20, r3, r9
li r9, PPC_CONTEXT_OFFSET_V21
@@ -397,7 +419,8 @@ PROC (_CPU_Context_switch_no_return):
stvx v31, r3, r9
mfvrsave r9
stw r9, PPC_CONTEXT_OFFSET_VRSAVE(r3)
#endif
#endif /* __PPC_VRSAVE__ */
#endif /* PPC_MULTILIB_ALTIVEC */
#ifdef PPC_MULTILIB_FPU
stfd f14, PPC_CONTEXT_OFFSET_F14(r3)
@@ -461,6 +484,14 @@ restore_context:
PPC_REG_LOAD r1, PPC_CONTEXT_OFFSET_GPR1(r5)
PPC_REG_LOAD r8, PPC_CONTEXT_OFFSET_LR(r5)
#ifdef PPC_MULTILIB_ALTIVEC
li r10, PPC_CONTEXT_OFFSET_VSCR
lvewx v0, r5, r10
#ifdef __PPC_VRSAVE__
lwz r9, PPC_CONTEXT_OFFSET_VRSAVE(r5)
#endif
#endif
PPC_GPR_LOAD r14, PPC_CONTEXT_OFFSET_GPR14(r5)
PPC_GPR_LOAD r15, PPC_CONTEXT_OFFSET_GPR15(r5)
@@ -494,6 +525,15 @@ restore_context:
lwz r11, PPC_CONTEXT_OFFSET_ISR_DISPATCH_DISABLE(r5)
#ifdef PPC_MULTILIB_ALTIVEC
mtvscr v0
#ifdef __PPC_VRSAVE__
mtvrsave r9
andi. r9, r9, 0xfff
bne .Laltivec_restore
.Laltivec_restore_continue:
#else /* __PPC_VRSAVE__ */
li r9, PPC_CONTEXT_OFFSET_V20
lvx v20, r5, r9
li r9, PPC_CONTEXT_OFFSET_V21
@@ -520,7 +560,8 @@ restore_context:
lvx v31, r5, r9
lwz r9, PPC_CONTEXT_OFFSET_VRSAVE(r5)
mtvrsave r9
#endif
#endif /* __PPC_VRSAVE__ */
#endif /* PPC_MULTILIB_ALTIVEC */
#ifdef PPC_MULTILIB_FPU
lfd f14, PPC_CONTEXT_OFFSET_F14(r5)
@@ -567,6 +608,13 @@ PROC (_CPU_Context_restore):
li r3, 0
#endif
#if defined(PPC_MULTILIB_ALTIVEC) && defined(__PPC_VRSAVE__)
/* Mark v0 as used since we need it to get the VSCR */
mfvrsave r9
oris r8, r9, 0x8000
mtvrsave r8
#endif
b restore_context
#ifdef RTEMS_SMP
@@ -595,3 +643,105 @@ PROC (_CPU_Context_restore):
b .Lcheck_is_executing
#endif
#if defined(PPC_MULTILIB_ALTIVEC) && defined(__PPC_VRSAVE__)
.Laltivec_save:
/*
* Let X be VRSAVE, calculate:
*
* Z = X & 0x777
* Z = Z + 0x777
* X = X | Z
*
* Afterwards, we have in X for each group of four non-volatile VR
* registers:
*
* 0111b, if VRSAVE group of four registers == 0
* 1XXXb, if VRSAVE group of four registers != 0
*/
andi. r10, r9, 0x777
addi r10, r10, 0x777
or r9, r9, r10
mtcr r9
bf 20, .Laltivec_save_v24
li r9, PPC_CONTEXT_OFFSET_V20
stvx v20, r3, r9
li r9, PPC_CONTEXT_OFFSET_V21
stvx v21, r3, r9
li r9, PPC_CONTEXT_OFFSET_V22
stvx v22, r3, r9
li r9, PPC_CONTEXT_OFFSET_V23
stvx v23, r3, r9
.Laltivec_save_v24:
bf 24, .Laltivec_save_v28
li r9, PPC_CONTEXT_OFFSET_V24
stvx v24, r3, r9
li r9, PPC_CONTEXT_OFFSET_V25
stvx v25, r3, r9
li r9, PPC_CONTEXT_OFFSET_V26
stvx v26, r3, r9
li r9, PPC_CONTEXT_OFFSET_V27
stvx v27, r3, r9
.Laltivec_save_v28:
bf 28, .Laltivec_save_continue
li r9, PPC_CONTEXT_OFFSET_V28
stvx v28, r3, r9
li r9, PPC_CONTEXT_OFFSET_V29
stvx v29, r3, r9
li r9, PPC_CONTEXT_OFFSET_V30
stvx v30, r3, r9
li r9, PPC_CONTEXT_OFFSET_V31
stvx v31, r3, r9
b .Laltivec_save_continue
.Laltivec_restore:
/* See comment at .Laltivec_save */
andi. r10, r9, 0x777
addi r10, r10, 0x777
or r9, r9, r10
mtcr r9
bf 20, .Laltivec_restore_v24
li r9, PPC_CONTEXT_OFFSET_V20
lvx v20, r5, r9
li r9, PPC_CONTEXT_OFFSET_V21
lvx v21, r5, r9
li r9, PPC_CONTEXT_OFFSET_V22
lvx v22, r5, r9
li r9, PPC_CONTEXT_OFFSET_V23
lvx v23, r5, r9
.Laltivec_restore_v24:
bf 24, .Laltivec_restore_v28
li r9, PPC_CONTEXT_OFFSET_V24
lvx v24, r5, r9
li r9, PPC_CONTEXT_OFFSET_V25
lvx v25, r5, r9
li r9, PPC_CONTEXT_OFFSET_V26
lvx v26, r5, r9
li r9, PPC_CONTEXT_OFFSET_V27
lvx v27, r5, r9
.Laltivec_restore_v28:
bf 28, .Laltivec_restore_continue
li r9, PPC_CONTEXT_OFFSET_V28
lvx v28, r5, r9
li r9, PPC_CONTEXT_OFFSET_V29
lvx v29, r5, r9
li r9, PPC_CONTEXT_OFFSET_V30
lvx v30, r5, r9
li r9, PPC_CONTEXT_OFFSET_V31
lvx v31, r5, r9
b .Laltivec_restore_continue
#endif /* PPC_MULTILIB_ALTIVEC && __PPC_VRSAVE__ */