summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/sparc/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/cpu/sparc/cpu.c')
-rw-r--r--cpukit/score/cpu/sparc/cpu.c65
1 files changed, 45 insertions, 20 deletions
diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c
index 5bea27fda5..8916a7d988 100644
--- a/cpukit/score/cpu/sparc/cpu.c
+++ b/cpukit/score/cpu/sparc/cpu.c
@@ -8,6 +8,8 @@
* COPYRIGHT (c) 1989-2007.
* On-Line Applications Research Corporation (OAR).
*
+ * Copyright (c) 2017 embedded brains GmbH
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
@@ -21,6 +23,7 @@
#include <rtems/score/isr.h>
#include <rtems/score/percpu.h>
#include <rtems/score/tls.h>
+#include <rtems/score/thread.h>
#include <rtems/rtems/cache.h>
#if SPARC_HAS_FPU == 1
@@ -29,6 +32,14 @@
== SPARC_PER_CPU_FSR_OFFSET,
SPARC_PER_CPU_FSR_OFFSET
);
+
+ #if defined(SPARC_USE_LAZY_FP_SWITCH)
+ RTEMS_STATIC_ASSERT(
+ offsetof( Per_CPU_Control, cpu_per_cpu.fp_owner)
+ == SPARC_PER_CPU_FP_OWNER_OFFSET,
+ SPARC_PER_CPU_FP_OWNER_OFFSET
+ );
+ #endif
#endif
#define SPARC_ASSERT_OFFSET(field, off) \
@@ -99,6 +110,30 @@ SPARC_ASSERT_ISF_OFFSET(i7, I7);
SPARC_ASSERT_ISF_OFFSET(y, Y);
SPARC_ASSERT_ISF_OFFSET(tpc, TPC);
+#define SPARC_ASSERT_FP_OFFSET(field, off) \
+ RTEMS_STATIC_ASSERT( \
+ offsetof(Context_Control_fp, field) == SPARC_FP_CONTEXT_OFFSET_ ## off, \
+ Context_Control_fp_offset_ ## field \
+ )
+
+SPARC_ASSERT_FP_OFFSET(f0_f1, F0_F1);
+SPARC_ASSERT_FP_OFFSET(f2_f3, F2_F3);
+SPARC_ASSERT_FP_OFFSET(f4_f5, F4_F5);
+SPARC_ASSERT_FP_OFFSET(f6_f7, F6_F7);
+SPARC_ASSERT_FP_OFFSET(f8_f9, F8_F9);
+SPARC_ASSERT_FP_OFFSET(f10_f11, F10_F11);
+SPARC_ASSERT_FP_OFFSET(f12_f13, F12_F13);
+SPARC_ASSERT_FP_OFFSET(f14_f15, F14_F15);
+SPARC_ASSERT_FP_OFFSET(f16_f17, F16_F17);
+SPARC_ASSERT_FP_OFFSET(f18_f19, F18_F19);
+SPARC_ASSERT_FP_OFFSET(f20_f21, F20_F21);
+SPARC_ASSERT_FP_OFFSET(f22_f23, F22_F23);
+SPARC_ASSERT_FP_OFFSET(f24_f25, F24_F25);
+SPARC_ASSERT_FP_OFFSET(f26_f27, F26_F27);
+SPARC_ASSERT_FP_OFFSET(f28_f29, F28_F29);
+SPARC_ASSERT_FP_OFFSET(f30_f31, F30_F31);
+SPARC_ASSERT_FP_OFFSET(fsr, FSR);
+
RTEMS_STATIC_ASSERT(
sizeof(SPARC_Minimum_stack_frame) == SPARC_MINIMUM_STACK_FRAME_SIZE,
SPARC_MINIMUM_STACK_FRAME_SIZE
@@ -110,10 +145,6 @@ RTEMS_STATIC_ASSERT(
CPU_Interrupt_frame_alignment
);
-#if (SPARC_HAS_FPU == 1) && !defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
-Context_Control_fp _CPU_Null_fp_context;
-#endif
-
/*
* _CPU_Initialize
*
@@ -129,22 +160,16 @@ Context_Control_fp _CPU_Null_fp_context;
void _CPU_Initialize(void)
{
-#if (SPARC_HAS_FPU == 1) && !defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
- Context_Control_fp *pointer;
- uint32_t psr;
-
- sparc_get_psr( psr );
- psr |= SPARC_PSR_EF_MASK;
- sparc_set_psr( psr );
-
- /*
- * This seems to be the most appropriate way to obtain an initial
- * FP context on the SPARC. The NULL fp context is copied it to
- * the task's FP context during Context_Initialize.
- */
-
- pointer = &_CPU_Null_fp_context;
- _CPU_Context_save_fp( &pointer );
+#if defined(SPARC_USE_LAZY_FP_SWITCH)
+ __asm__ volatile (
+ ".global SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET\n"
+ ".set SPARC_THREAD_CONTROL_REGISTERS_FP_CONTEXT_OFFSET, %0\n"
+ ".global SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET\n"
+ ".set SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET, %1\n"
+ :
+ : "i" (offsetof(Thread_Control, Registers.fp_context)),
+ "i" (offsetof(Thread_Control, fp_context))
+ );
#endif
}