On Fri, May 29, 2015 at 8:54 AM, Sebastian Huber <sebastian.hu...@embedded-brains.de> wrote: > Update #2270. > --- > cpukit/score/cpu/sparc/cpu.c | 16 ++++++++++++ > cpukit/score/cpu/sparc/cpu_asm.S | 44 > ++++++++++++++++++++++++++++++++ > cpukit/score/cpu/sparc/rtems/score/cpu.h | 22 ++++++++++++++-- > 3 files changed, 80 insertions(+), 2 deletions(-) > > diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c > index bab0040..b2f67c4 100644 > --- a/cpukit/score/cpu/sparc/cpu.c > +++ b/cpukit/score/cpu/sparc/cpu.c > @@ -134,6 +134,10 @@ void _CPU_Initialize(void) > #if (SPARC_HAS_FPU == 1) > Context_Control_fp *pointer; > uint32_t psr; > +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE > + Per_CPU_Control *cpu_self; > + uint32_t isr_dispatch_disable; > +#endif > > sparc_get_psr( psr ); > psr |= SPARC_PSR_EF_MASK; > @@ -146,7 +150,19 @@ void _CPU_Initialize(void) > */ > > pointer = &_CPU_Null_fp_context; > + > +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE > + cpu_self = _Per_CPU_Get(); > + isr_dispatch_disable = cpu_self->cpu_per_cpu.isr_dispatch_disable; > + cpu_self->cpu_per_cpu.isr_dispatch_disable = 1; > + pointer->is_valid = 1; > +#endif > + > _CPU_Context_save_fp( &pointer ); > + > +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE > + cpu_self->cpu_per_cpu.isr_dispatch_disable = isr_dispatch_disable; > +#endif > #endif > } > > diff --git a/cpukit/score/cpu/sparc/cpu_asm.S > b/cpukit/score/cpu/sparc/cpu_asm.S > index 3fa0532..fd63f19 100644 > --- a/cpukit/score/cpu/sparc/cpu_asm.S > +++ b/cpukit/score/cpu/sparc/cpu_asm.S > @@ -44,7 +44,26 @@ > .align 4 > PUBLIC(_CPU_Context_save_fp) > SYM(_CPU_Context_save_fp): > +#if CPU_USE_DEFERRED_FP_SWITCH == TRUE > ld [%o0], %o1 > +#else > + /* > + * On SMP configurations we cannot use the deferred floating point > + * switch. Save the FP context only in case we have an interrupted > + * thread (indicated by a non-zero per-CPU ISR dispatch disable > flag). > + * This works since the complete floating point context is volatile > on > + * SPARC. > + */ > + ld [%g6 + SPARC_PER_CPU_ISR_DISPATCH_DISABLE], %o2 > + cmp %o2, 0 > + bne do_save_fp > + ld [%o0], %o1 > + jmp %o7 + 8 > + nop > + > +do_save_fp: > +#endif > + > std %f0, [%o1 + FO_F1_OFFSET] > std %f2, [%o1 + F2_F3_OFFSET] > std %f4, [%o1 + F4_F5_OFFSET] > @@ -61,6 +80,15 @@ SYM(_CPU_Context_save_fp): > std %f26, [%o1 + F26_F27_OFFSET] > std %f28, [%o1 + F28_F29_OFFSET] > std %f30, [%o1 + F3O_F31_OFFSET] > + > +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE > + /* > + * Set the is valid flag of the floating point context to true. It > is > + * store here to store the fields in sequence. > + */ > + st %o2, [%o1 + SPARC_FP_CONTEXT_IS_VALID_OFFSET] > +#endif > + > jmp %o7 + 8 > st %fsr, [%o1 + FSR_OFFSET] > > @@ -81,6 +109,22 @@ SYM(_CPU_Context_save_fp): > PUBLIC(_CPU_Context_restore_fp) > SYM(_CPU_Context_restore_fp): > ld [%o0], %o1 > + > +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE > + /* > + * Check if we have a valid floating point context. Clear the is > valid > + * flag. Restore the floating point context if necessary. > + */ > + ld [%o1 + SPARC_FP_CONTEXT_IS_VALID_OFFSET], %o2 > + cmp %o2, 0 > + bne do_restore_fp > + st %g0, [%o1 + SPARC_FP_CONTEXT_IS_VALID_OFFSET] > + jmp %o7 + 8 > + nop > + > +do_restore_fp: > +#endif > + > ldd [%o1 + FO_F1_OFFSET], %f0 > ldd [%o1 + F2_F3_OFFSET], %f2 > ldd [%o1 + F4_F5_OFFSET], %f4 > diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h > b/cpukit/score/cpu/sparc/rtems/score/cpu.h > index 02891b0..e51a4ab 100644 > --- a/cpukit/score/cpu/sparc/rtems/score/cpu.h > +++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h > @@ -609,6 +609,10 @@ typedef struct { > double f28_f29; > /** This will contain the contents of the f30 and f31 register. */ > double f30_f31; > +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE > + /** Indicates if the context is valid. */ > + uint32_t is_valid; Is it the case that is_valid is only true during a context switch while interrupt handling (dispatch disabled)? I'd appreciate a bit more clarity in this comment. Is there a need to put is_valid before fsr? if the #if controlled field goes to the end of the block, then that can simplify the below offset calculations.
> +#endif > /** This will contain the contents of the floating point status register. > */ > uint32_t fsr; > } Context_Control_fp; > @@ -651,11 +655,25 @@ typedef struct { > #define F28_F29_OFFSET 0x70 > /** This macro defines an offset into the FPU context for use in assembly. */ > #define F3O_F31_OFFSET 0x78 > + > +#if CPU_USE_DEFERRED_FP_SWITCH == FALSE > + /** This macro defines an offset into the FPU context for use in assembly. > */ > + #define SPARC_FP_CONTEXT_IS_VALID_OFFSET 0x80 > +#endif > + > /** This macro defines an offset into the FPU context for use in assembly. */ > -#define FSR_OFFSET 0x80 > +#if CPU_USE_DEFERRED_FP_SWITCH == TRUE > + #define FSR_OFFSET 0x80 > +#else > + #define FSR_OFFSET 0x84 > +#endif > > /** This defines the size of the FPU context area for use in assembly. */ > -#define CONTEXT_CONTROL_FP_SIZE 0x84 > +#if CPU_USE_DEFERRED_FP_SWITCH == TRUE > + #define CONTEXT_CONTROL_FP_SIZE 0x84 > +#else > + #define CONTEXT_CONTROL_FP_SIZE 0x88 > +#endif > I'd prefer to always have the #if check the same direction, i.e. always check if it is FALSE. > #ifndef ASM > > -- > 1.8.4.5 > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel