summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Krutwig <alexander.krutwig@embedded-brains.de>2015-04-24 16:05:50 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-21 09:37:36 +0200
commit1c59cad4aa40238c1aa3085adf3d079114c077b8 (patch)
treed8c7bc8d2bcaa3d26aba05afa6cb1222aceb8efc
parentdoc: Clarify SPARC floating point ABI (diff)
downloadrtems-1c59cad4aa40238c1aa3085adf3d079114c077b8.tar.bz2
sparc: Add support for sptests/spcontext01
Implement _CPU_Context_validate() and _CPU_Context_volatile_clobber(). Update #2270.
-rw-r--r--cpukit/score/cpu/sparc/Makefile.am2
-rw-r--r--cpukit/score/cpu/sparc/rtems/score/cpu.h12
-rw-r--r--cpukit/score/cpu/sparc/sparc-context-validate.S368
-rw-r--r--cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S156
4 files changed, 528 insertions, 10 deletions
diff --git a/cpukit/score/cpu/sparc/Makefile.am b/cpukit/score/cpu/sparc/Makefile.am
index c6ea1c3da9..8cf4f4a65a 100644
--- a/cpukit/score/cpu/sparc/Makefile.am
+++ b/cpukit/score/cpu/sparc/Makefile.am
@@ -11,6 +11,8 @@ include_rtems_score_HEADERS += rtems/score/cpuatomic.h
noinst_LIBRARIES = libscorecpu.a
libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_SOURCES += sparc-context-volatile-clobber.S
+libscorecpu_a_SOURCES += sparc-context-validate.S
libscorecpu_a_SOURCES += sparc-counter.c
libscorecpu_a_SOURCES += sparcv8-atomic.c
libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h
index 235b3652ac..64e87509b4 100644
--- a/cpukit/score/cpu/sparc/rtems/score/cpu.h
+++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h
@@ -1216,17 +1216,9 @@ void _CPU_Context_restore_fp(
Context_Control_fp **fp_context_ptr
);
-static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
-{
- /* TODO */
-}
+void _CPU_Context_volatile_clobber( uintptr_t pattern );
-static inline void _CPU_Context_validate( uintptr_t pattern )
-{
- while (1) {
- /* TODO */
- }
-}
+void _CPU_Context_validate( uintptr_t pattern );
typedef struct {
uint32_t trap;
diff --git a/cpukit/score/cpu/sparc/sparc-context-validate.S b/cpukit/score/cpu/sparc/sparc-context-validate.S
new file mode 100644
index 0000000000..0ee7177d73
--- /dev/null
+++ b/cpukit/score/cpu/sparc/sparc-context-validate.S
@@ -0,0 +1,368 @@
+/*
+ * 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 FRAME_OFFSET_BUFFER (CPU_MINIMUM_STACK_FRAME_SIZE)
+#define FRAME_OFFSET_L0 (FRAME_OFFSET_BUFFER + 0x04)
+#define FRAME_OFFSET_L1 (FRAME_OFFSET_L0 + 0x04)
+#define FRAME_OFFSET_L2 (FRAME_OFFSET_L1 + 0x04)
+#define FRAME_OFFSET_L3 (FRAME_OFFSET_L2 + 0x04)
+#define FRAME_OFFSET_L4 (FRAME_OFFSET_L3 + 0x04)
+#define FRAME_OFFSET_L5 (FRAME_OFFSET_L4 + 0x04)
+#define FRAME_OFFSET_L6 (FRAME_OFFSET_L5 + 0x04)
+#define FRAME_OFFSET_L7 (FRAME_OFFSET_L6 + 0x04)
+#define FRAME_OFFSET_I0 (FRAME_OFFSET_L7 + 0x04)
+#define FRAME_OFFSET_I1 (FRAME_OFFSET_I0 + 0x04)
+#define FRAME_OFFSET_I2 (FRAME_OFFSET_I1 + 0x04)
+#define FRAME_OFFSET_I3 (FRAME_OFFSET_I2 + 0x04)
+#define FRAME_OFFSET_I4 (FRAME_OFFSET_I3 + 0x04)
+#define FRAME_OFFSET_I5 (FRAME_OFFSET_I4 + 0x04)
+#define FRAME_OFFSET_I6 (FRAME_OFFSET_I5 + 0x04)
+#define FRAME_OFFSET_I7 (FRAME_OFFSET_I6 + 0x04)
+#define FRAME_OFFSET_SP (FRAME_OFFSET_I7 + 0x04)
+#define FRAME_END (FRAME_OFFSET_SP + 0x04)
+#define FRAME_SIZE \
+ ((FRAME_END + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1))
+
+.macro check_register reg
+ sub %g1, 1, %g1
+ cmp %g1, \reg
+ bne restore_registers
+ nop
+.endm
+
+.macro check_float_register reg
+ sub %g1, 1, %g1
+ st \reg, [%sp + FRAME_OFFSET_BUFFER]
+ ld [%sp + FRAME_OFFSET_BUFFER], %o1
+ cmp %g1, %o1
+ bne restore_registers
+ nop
+.endm
+
+.macro check_fsr_register reg
+ st \reg, [%sp + FRAME_OFFSET_BUFFER]
+ ld [%sp + FRAME_OFFSET_BUFFER], %o1
+ sub %g1, 1, %g1
+ clr %g3
+ sethi %hi(0xCF800000), %g3
+ or %g3, %lo(0x0FFF), %g3
+ and %g1, %g3, %g3
+ and %o1, %g3, %o1
+ cmp %o1, %g3
+ bne restore_registers
+ nop
+.endm
+
+.macro write_register reg
+ add %g1, 1, %g1
+ mov %g1, \reg
+.endm
+
+.macro write_float_register reg
+ add %g1, 1, %g1
+ st %g1, [%sp + FRAME_OFFSET_BUFFER]
+ ld [%sp + FRAME_OFFSET_BUFFER], \reg
+.endm
+
+.macro write_fsr_register reg
+ st \reg, [%sp + FRAME_OFFSET_BUFFER]
+ ld [%sp + FRAME_OFFSET_BUFFER], %o1
+ add %g1, 1, %g1
+ clr %g3
+
+ /*
+ * FSR is masked with undefined, reserved or system-specific values
+ * (e.g. FPU architecture version, FP queue).
+ */
+ sethi %hi(0xCF800000), %g3
+ or %g3, %lo(0x0FFF), %g3
+ and %g1, %g3, %g3
+ or %o1, %g3, %g3
+ st %g3, [%sp + FRAME_OFFSET_BUFFER]
+ ld [%sp + FRAME_OFFSET_BUFFER], \reg
+.endm
+
+ .align 4
+ PUBLIC(_CPU_Context_validate)
+SYM(_CPU_Context_validate):
+
+ /*
+ * g2 checks if the Floating Point Unit in the Processor Status
+ * Register (PSR) is set.
+ */
+ mov %psr, %g2
+ sethi %hi(SPARC_PSR_EF_MASK), %g3
+ and %g2, %g3, %g2
+
+ /* g1 is used to save the original pattern */
+ mov %o0, %g1
+
+ /* g4 establishes window counter */
+ clr %g4
+
+ add %sp, -FRAME_SIZE, %sp
+
+ st %l0, [%sp + FRAME_OFFSET_L0]
+ st %l1, [%sp + FRAME_OFFSET_L1]
+ st %l2, [%sp + FRAME_OFFSET_L2]
+ st %l3, [%sp + FRAME_OFFSET_L3]
+ st %l4, [%sp + FRAME_OFFSET_L4]
+ st %l5, [%sp + FRAME_OFFSET_L5]
+ st %l6, [%sp + FRAME_OFFSET_L6]
+ st %l7, [%sp + FRAME_OFFSET_L7]
+ st %i0, [%sp + FRAME_OFFSET_I0]
+ st %i1, [%sp + FRAME_OFFSET_I1]
+ st %i2, [%sp + FRAME_OFFSET_I2]
+ st %i3, [%sp + FRAME_OFFSET_I3]
+ st %i4, [%sp + FRAME_OFFSET_I4]
+ st %i5, [%sp + FRAME_OFFSET_I5]
+ st %i6, [%sp + FRAME_OFFSET_I6]
+ st %i7, [%sp + FRAME_OFFSET_I7]
+ st %sp, [%sp + FRAME_OFFSET_SP]
+
+ cmp %g4, 0
+ bne write_locals_and_outputs
+ nop
+ be check_for_fp
+ nop
+
+new_check_cycle:
+ clr %g4
+ sub %g1, 1, %g1
+
+ /* Write pattern values into registers */
+
+check_for_fp:
+ cmp %g2, 0
+ be write_y
+ nop
+
+ write_fsr_register %fsr
+ write_float_register %f0
+ write_float_register %f1
+ write_float_register %f2
+ write_float_register %f3
+ write_float_register %f4
+ write_float_register %f5
+ write_float_register %f6
+ write_float_register %f7
+ write_float_register %f8
+ write_float_register %f9
+ write_float_register %f10
+ write_float_register %f11
+ write_float_register %f12
+ write_float_register %f13
+ write_float_register %f14
+ write_float_register %f15
+ write_float_register %f16
+ write_float_register %f17
+ write_float_register %f18
+ write_float_register %f19
+ write_float_register %f20
+ write_float_register %f21
+ write_float_register %f22
+ write_float_register %f23
+ write_float_register %f24
+ write_float_register %f25
+ write_float_register %f26
+ write_float_register %f27
+ write_float_register %f28
+ write_float_register %f29
+ write_float_register %f30
+ write_float_register %f31
+
+write_y:
+ write_register %y
+
+ write_register %i0
+ write_register %i1
+ write_register %i2
+ write_register %i3
+ write_register %i4
+ write_register %i5
+ /* Don't write register $i6 => frame pointer */
+ /* Don't write register $i7 => return address */
+ b write_locals_and_outputs
+ nop
+
+switch_to_next_window:
+ save %sp, -FRAME_SIZE, %sp
+
+write_locals_and_outputs:
+ /* l0 is used as a scratch register */
+ write_register %l1
+ write_register %l2
+ write_register %l3
+ write_register %l4
+ write_register %l5
+ write_register %l6
+ write_register %l7
+ write_register %o1
+ write_register %o2
+ write_register %o3
+ write_register %o4
+ write_register %o5
+ /* Don't write register $o6 => stack pointer */
+ /* Don't write register $o7 => return address */
+
+ add %g4, 1, %g4
+ cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
+ bne switch_to_next_window
+ nop
+
+ /* Dummy increment to set up reverse mechanism for checking process */
+ add %g1, 1, %g1
+ clr %g4
+
+ /* Checking begins here */
+window_checking:
+ cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
+ be y_checking
+ nop
+
+further_checking:
+ cmp %g4, 0
+ bne goto_local_registers
+ nop
+
+ /* Check normal registers */
+ check_register %o5
+ check_register %o4
+ check_register %o3
+ check_register %o2
+ check_register %o1
+
+goto_local_registers:
+ check_register %l7
+ check_register %l6
+ check_register %l5
+ check_register %l4
+ check_register %l3
+ check_register %l2
+ check_register %l1
+
+ check_register %i5
+ check_register %i4
+ check_register %i3
+ check_register %i2
+ check_register %i1
+ /*
+ For the last window i0 also needs to be checked as this variable
+ is not overwritten by the outputs of another window.
+ */
+ add %g4, 1, %g4
+ cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
+ bne dont_check_i0
+ nop
+ check_register %i0
+ b y_checking
+ nop
+
+dont_check_i0:
+ restore
+
+ ba window_checking
+ nop
+
+ /* Check Y register */
+y_checking:
+ mov %y, %o1
+ check_register %o1
+ cmp %g2, 0
+ be new_check_cycle
+ nop
+
+ /* Check floating point registers */
+ check_float_register %f31
+ check_float_register %f30
+ check_float_register %f29
+ check_float_register %f28
+ check_float_register %f27
+ check_float_register %f26
+ check_float_register %f25
+ check_float_register %f24
+ check_float_register %f23
+ check_float_register %f22
+ check_float_register %f21
+ check_float_register %f20
+ check_float_register %f19
+ check_float_register %f18
+ check_float_register %f17
+ check_float_register %f16
+ check_float_register %f15
+ check_float_register %f14
+ check_float_register %f13
+ check_float_register %f12
+ check_float_register %f11
+ check_float_register %f10
+ check_float_register %f9
+ check_float_register %f8
+ check_float_register %f7
+ check_float_register %f6
+ check_float_register %f5
+ check_float_register %f4
+ check_float_register %f3
+ check_float_register %f2
+ check_float_register %f1
+ check_float_register %f0
+ check_fsr_register %fsr
+
+ be new_check_cycle
+ nop
+
+ /****** RESTORE STARTS HERE *******/
+
+ /* Restore non-volatile registers */
+
+restore_registers:
+ and %g4, (SPARC_NUMBER_OF_REGISTER_WINDOWS - 1), %g4
+ cmp %g4, 0
+ be real_restore
+ nop
+ restore
+ sub %g4, 1, %g4
+ bne restore_registers
+ nop
+
+real_restore:
+ ld [%sp + FRAME_OFFSET_L0], %l0
+ ld [%sp + FRAME_OFFSET_L1], %l1
+ ld [%sp + FRAME_OFFSET_L2], %l2
+ ld [%sp + FRAME_OFFSET_L3], %l3
+ ld [%sp + FRAME_OFFSET_L4], %l4
+ ld [%sp + FRAME_OFFSET_L5], %l5
+ ld [%sp + FRAME_OFFSET_L6], %l6
+ ld [%sp + FRAME_OFFSET_L7], %l7
+ ld [%sp + FRAME_OFFSET_I0], %i0
+ ld [%sp + FRAME_OFFSET_I1], %i1
+ ld [%sp + FRAME_OFFSET_I2], %i2
+ ld [%sp + FRAME_OFFSET_I3], %i3
+ ld [%sp + FRAME_OFFSET_I4], %i4
+ ld [%sp + FRAME_OFFSET_I5], %i5
+ ld [%sp + FRAME_OFFSET_I6], %i6
+ ld [%sp + FRAME_OFFSET_I7], %i7
+
+ sub %sp, -FRAME_SIZE, %sp
+
+return_value:
+ /* Load callback address and jump back */
+ jmp %o7 + 8
+ add %sp, FRAME_SIZE, %sp
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