summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S')
-rw-r--r--cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S156
1 files changed, 156 insertions, 0 deletions
diff --git a/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S b/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S
new file mode 100644
index 0000000000..6e364cd3f6
--- /dev/null
+++ b/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/asm.h>
+#include <rtems/score/cpu.h>
+
+#define SCRATCH_0 (CPU_MINIMUM_STACK_FRAME_SIZE)
+#define SCRATCH_1 (SCRATCH_0 + 0x04)
+#define FRAME_END (SCRATCH_1 + 0x04)
+#define FRAME_SIZE \
+ ((FRAME_END + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1))
+
+.macro clobber_register reg
+ sub %g2, 1, %g2
+ mov %g2, \reg
+.endm
+
+.macro clobber_fp_register reg
+ sub %g2, 1, %g2
+ st %g2, [%sp + SCRATCH_0]
+ ld [%sp + SCRATCH_0], \reg
+.endm
+
+ .section ".bss"
+ .align 4
+
+ /*
+ * Use a global variable to vary the clobbered windows in each
+ * invocation to test the window overflow and underflow conditions.
+ */
+window_clobber_count:
+ .skip 4
+
+ .section ".text"
+ .align 4
+
+ PUBLIC(_CPU_Context_volatile_clobber)
+SYM(_CPU_Context_volatile_clobber):
+
+ /* Increment number of flushed windows by one */
+ sethi %hi(window_clobber_count), %o1
+ ld [%o1 + %lo(window_clobber_count)], %o2
+ add %o2, 1, %o2
+ st %o2, [%o1 + %lo(window_clobber_count)]
+
+ /* Clear window counter number */
+ clr %g1
+
+ /* Save pattern to global register */
+ mov %o0, %g2
+
+window_clobber:
+
+ /* Switch window */
+
+ save %sp, -FRAME_SIZE, %sp
+
+ /* Check how many windows shall be flushed */
+ sethi %hi(window_clobber_count), %o1
+ ld [%o1 + %lo(window_clobber_count)], %o2
+ st %o2, [%o1 + %lo(window_clobber_count)]
+ and %o2, (SPARC_NUMBER_OF_REGISTER_WINDOWS - 1), %o1
+ cmp %o1, 0
+ bne no_manual_update
+ nop
+ add %o1, SPARC_NUMBER_OF_REGISTER_WINDOWS, %o1
+
+no_manual_update:
+ /* Register to determine whether FPU is switched on */
+ mov %psr, %o2
+ sethi %hi(SPARC_PSR_EF_MASK), %o3
+ and %o3, %o2, %o2
+
+ clobber_register %o3
+ clobber_register %o4
+ clobber_register %o5
+ /* Don't overwrite return address $o7 */
+ clobber_register %g3
+ clobber_register %g4
+ clobber_register %y
+
+ cmp %o2, 0
+ be window_update_check
+ nop
+
+ clobber_fp_register %f0
+ clobber_fp_register %f1
+ clobber_fp_register %f2
+ clobber_fp_register %f3
+ clobber_fp_register %f4
+ clobber_fp_register %f5
+ clobber_fp_register %f6
+ clobber_fp_register %f7
+ clobber_fp_register %f8
+ clobber_fp_register %f9
+ clobber_fp_register %f10
+ clobber_fp_register %f11
+ clobber_fp_register %f12
+ clobber_fp_register %f13
+ clobber_fp_register %f14
+ clobber_fp_register %f15
+ clobber_fp_register %f16
+ clobber_fp_register %f17
+ clobber_fp_register %f18
+ clobber_fp_register %f19
+ clobber_fp_register %f20
+ clobber_fp_register %f21
+ clobber_fp_register %f22
+ clobber_fp_register %f23
+ clobber_fp_register %f24
+ clobber_fp_register %f25
+ clobber_fp_register %f26
+ clobber_fp_register %f27
+ clobber_fp_register %f28
+ clobber_fp_register %f29
+ clobber_fp_register %f30
+ clobber_fp_register %f31
+
+window_update_check:
+
+ /* Counter to how many windows were switched */
+ add %g1, 1, %g1
+ cmp %g1, %o1
+ bl window_clobber
+ nop
+
+restore_check:
+
+ cmp %g1, 0
+ be clobber_return
+ nop
+
+ restore
+ sub %g1, 1, %g1
+ ba restore_check
+ nop
+
+clobber_return:
+
+ jmp %o7 + 8
+ add %sp, FRAME_SIZE, %sp