summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/irq_asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/irq_asm.S')
-rw-r--r--c/src/lib/libbsp/sparc/shared/irq_asm.S54
1 files changed, 46 insertions, 8 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/irq_asm.S b/c/src/lib/libbsp/sparc/shared/irq_asm.S
index 1d76e7e728..7d0312b7e4 100644
--- a/c/src/lib/libbsp/sparc/shared/irq_asm.S
+++ b/c/src/lib/libbsp/sparc/shared/irq_asm.S
@@ -7,7 +7,7 @@
* COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR).
*
- * Copyright (c) 2014, 2016 embedded brains GmbH
+ * Copyright (c) 2014, 2017 embedded brains GmbH
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -218,7 +218,17 @@ done_flushing:
! The next load is in a delay slot, which is all right
#endif
+#if defined(SPARC_USE_LAZY_FP_SWITCH)
+ ld [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET], %g2
+#endif
ld [%o1 + PSR_OFFSET], %g1 ! g1 = heir psr with traps enabled
+#if defined(SPARC_USE_LAZY_FP_SWITCH)
+ sethi %hi(SPARC_PSR_EF_MASK), %g5
+ cmp %g2, %g0
+ bne,a .Lclear_psr_ef_done
+ andn %g1, %g5, %g1 ! g1 = heir psr w/o PSR[EF]
+.Lclear_psr_ef_done:
+#endif
andn %g1, SPARC_PSR_CWP_MASK, %g1 ! g1 = heir psr w/o cwp
or %g1, %g3, %g1 ! g1 = heir psr with cwp
mov %g1, %psr ! restore status register and
@@ -583,7 +593,7 @@ pil_fixed:
nop ! delay slot
#endif
-#if SPARC_HAS_FPU == 1
+#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
mov %l0, %g1 ! PSR[EF] value of interrupted context
ta SPARC_SWTRAP_IRQDIS_FP ! **** DISABLE INTERRUPTS ****
#else
@@ -652,10 +662,38 @@ isr_dispatch:
mov 0, %o1 ! ISR level for _Thread_Do_dispatch()
-#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
+#if defined(SPARC_USE_LAZY_FP_SWITCH)
/* Test if we interrupted a floating point thread (PSR[EF] == 1) */
andcc %l0, %l5, %g0
- be non_fp_thread_dispatch
+ be .Lnon_fp_thread_dispatch
+ ld [%g6 + PER_CPU_OFFSET_EXECUTING], %l6
+
+ /* Set new floating point unit owner to executing thread */
+ st %l6, [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET]
+
+ call SYM(_Thread_Do_dispatch)
+ mov %g6, %o0
+
+ /*
+ * If we are still the floating point unit owner, then reset the
+ * floating point unit owner to NULL, otherwise clear PSR[EF] in the
+ * interrupt frame and let the FP disabled system call do the floating
+ * point context save/restore.
+ */
+ ld [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET], %l7
+ cmp %l6, %l7
+ bne .Ldisable_fp
+ andn %l0, %l5, %l0
+ ba .Lthread_dispatch_done
+ st %g0, [%g6 + SPARC_PER_CPU_FP_OWNER_OFFSET]
+.Ldisable_fp:
+ ba .Lthread_dispatch_done
+ st %l0, [%fp + ISF_PSR_OFFSET]
+.Lnon_fp_thread_dispatch:
+#elif defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
+ /* Test if we interrupted a floating point thread (PSR[EF] == 1) */
+ andcc %l0, %l5, %g0
+ be .Lnon_fp_thread_dispatch
nop
/*
@@ -722,17 +760,17 @@ isr_dispatch:
ldd [%sp + FP_FRAME_OFFSET_F28_F29], %f28
ldd [%sp + FP_FRAME_OFFSET_F3O_F31], %f30
ld [%sp + FP_FRAME_OFFSET_FSR], %fsr
- ba thread_dispatch_done
+ ba .Lthread_dispatch_done
add %sp, FP_FRAME_SIZE, %sp
-non_fp_thread_dispatch:
+.Lnon_fp_thread_dispatch:
#endif
call SYM(_Thread_Do_dispatch)
mov %g6, %o0
-#if defined(SPARC_USE_SYNCHRONOUS_FP_SWITCH)
-thread_dispatch_done:
+#if SPARC_HAS_FPU == 1
+.Lthread_dispatch_done:
#endif
ta SPARC_SWTRAP_IRQDIS ! **** DISABLE INTERRUPTS ****