[PATCH] sparc: Save/restore only non-volatile context

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Feb 5 11:01:14 UTC 2014


The _CPU_Context_switch() is a normal function call.  The following
registers are volatile (the caller must assume that the register
contents are destroyed by the callee) according to "SYSTEM V APPLICATION
BINARY INTERFACE - SPARC Processor Supplement", Third Edition: g1, o0,
o1, o2, o3, o4, o5.  Drop these registers from the context.

Ensure that offset defines match the structure offsets
---
 c/src/lib/libbsp/sparc/shared/irq_asm.S  |   19 +-----
 cpukit/score/cpu/sparc/cpu.c             |   38 +++++++++++
 cpukit/score/cpu/sparc/rtems/score/cpu.h |  100 +++++++++++-------------------
 3 files changed, 78 insertions(+), 79 deletions(-)

diff --git a/c/src/lib/libbsp/sparc/shared/irq_asm.S b/c/src/lib/libbsp/sparc/shared/irq_asm.S
index 66125c7..20f10ba 100644
--- a/c/src/lib/libbsp/sparc/shared/irq_asm.S
+++ b/c/src/lib/libbsp/sparc/shared/irq_asm.S
@@ -52,9 +52,7 @@
         .align 4
         PUBLIC(_CPU_Context_switch)
 SYM(_CPU_Context_switch):
-        ! skip g0
-        st      %g1, [%o0 + G1_OFFSET]       ! save the global registers
-        std     %g2, [%o0 + G2_OFFSET]
+        std     %g2, [%o0 + G2_OFFSET]       ! save the global registers
         std     %g4, [%o0 + G4_OFFSET]
         std     %g6, [%o0 + G6_OFFSET]
 
@@ -68,10 +66,7 @@ SYM(_CPU_Context_switch):
         std     %i4, [%o0 + I4_OFFSET]
         std     %i6, [%o0 + I6_FP_OFFSET]
 
-        std     %o0, [%o0 + O0_OFFSET]       ! save the output registers
-        std     %o2, [%o0 + O2_OFFSET]
-        std     %o4, [%o0 + O4_OFFSET]
-        std     %o6, [%o0 + O6_SP_OFFSET]
+        std     %o6, [%o0 + O6_SP_OFFSET]    ! save the output registers
 
         ! o3 = self per-CPU control
         GET_SELF_CPU_CONTROL %o3, %o4
@@ -190,9 +185,7 @@ done_flushing:
         nop
         nop
 
-        ! skip g0
-        ld      [%o1 + G1_OFFSET], %g1        ! restore the global registers
-        ldd     [%o1 + G2_OFFSET], %g2
+        ldd     [%o1 + G2_OFFSET], %g2        ! restore the global registers
         ldd     [%o1 + G4_OFFSET], %g4
         ldd     [%o1 + G6_OFFSET], %g6
 
@@ -213,11 +206,7 @@ done_flushing:
         ldd     [%o1 + I4_OFFSET], %i4
         ldd     [%o1 + I6_FP_OFFSET], %i6
 
-        ldd     [%o1 + O2_OFFSET], %o2        ! restore the output registers
-        ldd     [%o1 + O4_OFFSET], %o4
-        ldd     [%o1 + O6_SP_OFFSET], %o6
-        ! do o0/o1 last to avoid destroying heir context pointer
-        ldd     [%o1 + O0_OFFSET], %o0        ! overwrite heir pointer
+        ldd     [%o1 + O6_SP_OFFSET], %o6     ! restore the output registers
 
         jmp     %o7 + 8                       ! return
         nop                                   ! delay slot
diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c
index 11e31f9..3e08c26 100644
--- a/cpukit/score/cpu/sparc/cpu.c
+++ b/cpukit/score/cpu/sparc/cpu.c
@@ -29,6 +29,44 @@ RTEMS_STATIC_ASSERT(
   SPARC_PER_CPU_ISR_DISPATCH_DISABLE
 );
 
+#define SPARC_ASSERT_OFFSET(field, off) \
+  RTEMS_STATIC_ASSERT( \
+    offsetof(Context_Control, field) == off ## _OFFSET, \
+    Context_Control_offset_ ## field \
+  )
+
+SPARC_ASSERT_OFFSET(g2_g3, G2);
+SPARC_ASSERT_OFFSET(g4, G4);
+SPARC_ASSERT_OFFSET(g5, G5);
+SPARC_ASSERT_OFFSET(g6, G6);
+SPARC_ASSERT_OFFSET(g7, G7);
+SPARC_ASSERT_OFFSET(l0, L0);
+SPARC_ASSERT_OFFSET(l1, L1);
+SPARC_ASSERT_OFFSET(l2, L2);
+SPARC_ASSERT_OFFSET(l3, L3);
+SPARC_ASSERT_OFFSET(l4, L4);
+SPARC_ASSERT_OFFSET(l5, L5);
+SPARC_ASSERT_OFFSET(l6, L6);
+SPARC_ASSERT_OFFSET(l7, L7);
+SPARC_ASSERT_OFFSET(i0, I0);
+SPARC_ASSERT_OFFSET(i1, I1);
+SPARC_ASSERT_OFFSET(i2, I2);
+SPARC_ASSERT_OFFSET(i3, I3);
+SPARC_ASSERT_OFFSET(i4, I4);
+SPARC_ASSERT_OFFSET(i5, I5);
+SPARC_ASSERT_OFFSET(i6_fp, I6_FP);
+SPARC_ASSERT_OFFSET(i7, I7);
+SPARC_ASSERT_OFFSET(o6_sp, O6_SP);
+SPARC_ASSERT_OFFSET(o7, O7);
+SPARC_ASSERT_OFFSET(psr, PSR);
+SPARC_ASSERT_OFFSET(isr_dispatch_disable, ISR_DISPATCH_DISABLE_STACK);
+
+RTEMS_STATIC_ASSERT(
+  (offsetof(Context_Control, g2_g3)
+     + offsetof(Context_Control, g4)) / 2 == G3_OFFSET,
+  Context_Control_offset_G3
+);
+
 /*
  *  This initializes the set of opcodes placed in each trap
  *  table entry.  The routine which installs a handler is responsible
diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h
index ae89311..42095a6 100644
--- a/cpukit/score/cpu/sparc/rtems/score/cpu.h
+++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h
@@ -401,20 +401,17 @@ typedef struct {
 /**
  * @brief SPARC basic context.
  *
- * This structure defines the basic integer and processor state context
- * for the SPARC architecture.
+ * This structure defines the non-volatile integer and processor state context
+ * for the SPARC architecture according to "SYSTEM V APPLICATION BINARY
+ * INTERFACE - SPARC Processor Supplement", Third Edition.
  */
 typedef struct {
   /**
-   * Using a double g0_g1 will put everything in this structure on a
+   * Using a double g2_g3 will put everything in this structure on a
    * double word boundary which allows us to use double word loads
    * and stores safely in the context switch.
    */
-  double     g0_g1;
-  /** This will contain the contents of the g2 register. */
-  uint32_t   g2;
-  /** This will contain the contents of the g3 register. */
-  uint32_t   g3;
+  double     g2_g3;
   /** This will contain the contents of the g4 register. */
   uint32_t   g4;
   /** This will contain the contents of the g5 register. */
@@ -458,21 +455,12 @@ typedef struct {
   /** This will contain the contents of the i7 register. */
   uint32_t   i7;
 
-  /** This will contain the contents of the o0 register. */
-  uint32_t   o0;
-  /** This will contain the contents of the o1 register. */
-  uint32_t   o1;
-  /** This will contain the contents of the o2 register. */
-  uint32_t   o2;
-  /** This will contain the contents of the o3 register. */
-  uint32_t   o3;
-  /** This will contain the contents of the o4 register. */
-  uint32_t   o4;
-  /** This will contain the contents of the o5 register. */
-  uint32_t   o5;
   /** This will contain the contents of the o6 (e.g. frame pointer) register. */
   uint32_t   o6_sp;
-  /** This will contain the contents of the o7 register. */
+  /**
+   * This will contain the contents of the o7 (e.g. address of CALL
+   * instruction) register.
+   */
   uint32_t   o7;
 
   /** This will contain the contents of the processor status register. */
@@ -500,80 +488,64 @@ typedef struct {
  */
 
 /** This macro defines an offset into the context for use in assembly. */
-#define G0_OFFSET    0x00
-/** This macro defines an offset into the context for use in assembly. */
-#define G1_OFFSET    0x04
+#define G2_OFFSET    0x00
 /** This macro defines an offset into the context for use in assembly. */
-#define G2_OFFSET    0x08
+#define G3_OFFSET    0x04
 /** This macro defines an offset into the context for use in assembly. */
-#define G3_OFFSET    0x0C
+#define G4_OFFSET    0x08
 /** This macro defines an offset into the context for use in assembly. */
-#define G4_OFFSET    0x10
+#define G5_OFFSET    0x0C
 /** This macro defines an offset into the context for use in assembly. */
-#define G5_OFFSET    0x14
+#define G6_OFFSET    0x10
 /** This macro defines an offset into the context for use in assembly. */
-#define G6_OFFSET    0x18
-/** This macro defines an offset into the context for use in assembly. */
-#define G7_OFFSET    0x1C
+#define G7_OFFSET    0x14
 
 /** This macro defines an offset into the context for use in assembly. */
-#define L0_OFFSET    0x20
+#define L0_OFFSET    0x18
 /** This macro defines an offset into the context for use in assembly. */
-#define L1_OFFSET    0x24
+#define L1_OFFSET    0x1C
 /** This macro defines an offset into the context for use in assembly. */
-#define L2_OFFSET    0x28
+#define L2_OFFSET    0x20
 /** This macro defines an offset into the context for use in assembly. */
-#define L3_OFFSET    0x2C
+#define L3_OFFSET    0x24
 /** This macro defines an offset into the context for use in assembly. */
-#define L4_OFFSET    0x30
+#define L4_OFFSET    0x28
 /** This macro defines an offset into the context for use in assembly. */
-#define L5_OFFSET    0x34
+#define L5_OFFSET    0x2C
 /** This macro defines an offset into the context for use in assembly. */
-#define L6_OFFSET    0x38
+#define L6_OFFSET    0x30
 /** This macro defines an offset into the context for use in assembly. */
-#define L7_OFFSET    0x3C
+#define L7_OFFSET    0x34
 
 /** This macro defines an offset into the context for use in assembly. */
-#define I0_OFFSET    0x40
+#define I0_OFFSET    0x38
 /** This macro defines an offset into the context for use in assembly. */
-#define I1_OFFSET    0x44
+#define I1_OFFSET    0x3C
 /** This macro defines an offset into the context for use in assembly. */
-#define I2_OFFSET    0x48
+#define I2_OFFSET    0x40
 /** This macro defines an offset into the context for use in assembly. */
-#define I3_OFFSET    0x4C
+#define I3_OFFSET    0x44
 /** This macro defines an offset into the context for use in assembly. */
-#define I4_OFFSET    0x50
+#define I4_OFFSET    0x48
 /** This macro defines an offset into the context for use in assembly. */
-#define I5_OFFSET    0x54
+#define I5_OFFSET    0x4C
 /** This macro defines an offset into the context for use in assembly. */
-#define I6_FP_OFFSET 0x58
+#define I6_FP_OFFSET 0x50
 /** This macro defines an offset into the context for use in assembly. */
-#define I7_OFFSET    0x5C
+#define I7_OFFSET    0x54
 
 /** This macro defines an offset into the context for use in assembly. */
-#define O0_OFFSET    0x60
-/** This macro defines an offset into the context for use in assembly. */
-#define O1_OFFSET    0x64
-/** This macro defines an offset into the context for use in assembly. */
-#define O2_OFFSET    0x68
-/** This macro defines an offset into the context for use in assembly. */
-#define O3_OFFSET    0x6C
-/** This macro defines an offset into the context for use in assembly. */
-#define O4_OFFSET    0x70
-/** This macro defines an offset into the context for use in assembly. */
-#define O5_OFFSET    0x74
-/** This macro defines an offset into the context for use in assembly. */
-#define O6_SP_OFFSET 0x78
+#define O6_SP_OFFSET 0x58
 /** This macro defines an offset into the context for use in assembly. */
-#define O7_OFFSET    0x7C
+#define O7_OFFSET    0x5C
 
 /** This macro defines an offset into the context for use in assembly. */
-#define PSR_OFFSET   0x80
+#define PSR_OFFSET   0x60
 /** This macro defines an offset into the context for use in assembly. */
-#define ISR_DISPATCH_DISABLE_STACK_OFFSET 0x84
+#define ISR_DISPATCH_DISABLE_STACK_OFFSET 0x64
 
 /** This defines the size of the context area for use in assembly. */
-#define CONTEXT_CONTROL_SIZE 0x88
+#define CONTEXT_CONTROL_SIZE 0x68
 
 #ifndef ASM
 /**
-- 
1.7.7




More information about the devel mailing list