[PATCH] SPARC Floating Point Context switch
Alexander Krutwig
alexander.krutwig at embedded-brains.de
Mon May 11 08:51:31 UTC 2015
two new Assembler Files for SPCONTEXT01 test on sparc
1) _CPU_Context_validate
2) _CPU_Context_volatile_clobber
Update #2270.
---
cpukit/score/cpu/sparc/Makefile.am | 2 +
cpukit/score/cpu/sparc/rtems/score/cpu.h | 12 +-
cpukit/score/cpu/sparc/sparc-context-validate.S | 367 +++++++++++++++++++++
.../cpu/sparc/sparc-context-volatile-clobber.S | 153 +++++++++
4 files changed, 524 insertions(+), 10 deletions(-)
create mode 100644 cpukit/score/cpu/sparc/sparc-context-validate.S
create mode 100644 cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S
diff --git a/cpukit/score/cpu/sparc/Makefile.am b/cpukit/score/cpu/sparc/Makefile.am
index c6ea1c3..8cf4f4a 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 235b365..64e8750 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 0000000..9e3f425
--- /dev/null
+++ b/cpukit/score/cpu/sparc/sparc-context-validate.S
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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_L0 (CPU_MINIMUM_STACK_FRAME_SIZE)
+#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_STACK_POINTER (FRAME_OFFSET_I7 + 0x04)
+#define BUFFER_STORAGE (FRAME_OFFSET_STACK_POINTER + 0x04)
+#define FRAME_SIZE (BUFFER_STORAGE + 0x04)
+
+#if ((FRAME_SIZE % CPU_ALIGNMENT) != 0)
+#define FRAME_SIZE (BUFFER_STORAGE + 0x04)
+#endif
+
+ .align 4
+ PUBLIC(_CPU_Context_validate)
+SYM(_CPU_Context_validate):
+
+startup:
+
+/* 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
+
+window_processing:
+
+ save %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_STACK_POINTER]
+
+ cmp %g4, 0
+ bne write_locals_and_outputs
+ nop
+
+.macro write_register reg
+ add %g1, 1, %g1
+ mov %g1, \reg
+.endm
+
+.macro write_float_register reg
+ add %g1, 1, %g1
+ st %g1, [%sp+BUFFER_STORAGE]
+ ld [%sp+BUFFER_STORAGE], \reg
+.endm
+
+.macro write_fsr_register reg
+ st \reg, [%sp+BUFFER_STORAGE]
+ ld [%sp+BUFFER_STORAGE], %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+BUFFER_STORAGE]
+ ld [%sp+BUFFER_STORAGE], \reg
+.endm
+
+/* Write pattern values into registers. */
+
+ cmp %g2, 0
+ be write_y
+ nop
+
+write_floats:
+ 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_inputs:
+ 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. */
+
+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. */
+
+write_all_registers:
+ add %g4, 1, %g4
+ cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
+ bne window_processing
+ nop
+
+dummy_increment:
+/* Dummy increment to set up reverse mechanism for checking process. */
+ add %g1, 1, %g1
+ clr %g4
+
+/* Checking begins here. */
+
+.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+BUFFER_STORAGE]
+ ld [%sp+BUFFER_STORAGE], %o1
+ cmp %g1, %o1
+ bne restore_registers
+ nop
+.endm
+
+.macro check_fsr_register reg
+ st \reg, [%sp+BUFFER_STORAGE]
+ ld [%sp+BUFFER_STORAGE], %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
+
+
+window_checking:
+ cmp %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
+ be y_checking
+ nop
+
+further_checking:
+ ld [%sp + FRAME_OFFSET_STACK_POINTER], %l0
+ cmp %l0, %sp
+ bne restore_registers
+ nop
+ 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. */
+ cmp %g4, (SPARC_NUMBER_OF_REGISTER_WINDOWS - 1)
+ bne dont_check_i0
+ nop
+ check_register %i0
+
+dont_check_i0:
+ restore
+ add %g4, 1, %g4
+
+ ba window_checking
+ nop
+
+/* Check Y register. */
+
+y_checking:
+ mov %y, %o1
+ check_register %o1
+ cmp %g2, 0
+ be startup
+ nop
+
+/* Check floating point registers. */
+
+float_checking:
+
+ 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 startup
+ nop
+
+/****** RESTORE STARTS HERE *******/
+
+/* Restore non-volatile registers. */
+
+restore_registers:
+
+ 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
+
+ and %g4, (SPARC_NUMBER_OF_REGISTER_WINDOWS - 1), %g4
+ cmp %g4, 0
+ be return_value
+ nop
+ restore
+ sub %g4, 1, %g4
+ bne restore_registers
+ nop
+
+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 0000000..8fbbac7
--- /dev/null
+++ b/cpukit/score/cpu/sparc/sparc-context-volatile-clobber.S
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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_SIZE (SCRATCH_1 + 0x04)
+
+ .global i
+ .section ".bss"
+ .align 4
+ .type i, #object
+ .size i, 4
+i:
+
+ .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(i), %o1
+ ld [%o1+%lo(i)], %o2
+ add %o2, 1, %o2
+ st %o2, [%o1+%lo(i)]
+
+ /* clear window counter number */
+ clr %g1
+
+ /* save pattern to global register */
+ mov %o0, %g2
+
+.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
+
+window_clobber:
+
+ /* switch window */
+
+ save %sp, -FRAME_SIZE, %sp
+
+ /* check how many windows shall be flushed*/
+ sethi %hi(i), %o1
+ ld [%o1+%lo(i)], %o2
+ st %o2, [%o1+%lo(i)]
+ 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_instance:
+ restore
+ sub %g1, 1, %g1
+ ba restore_check
+ nop
+
+clobber_return:
+
+ jmp %o7+8
+ add %sp, FRAME_SIZE, %sp
--
1.8.4.5
More information about the devel
mailing list