sparc: Save/restore only non-volatile context

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.
This commit is contained in:
Sebastian Huber
2014-02-05 11:36:05 +01:00
parent 62c5c4a564
commit 97cf623d4a
3 changed files with 78 additions and 79 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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
#define G2_OFFSET 0x00
/** This macro defines an offset into the context for use in assembly. */
#define G1_OFFSET 0x04
#define G3_OFFSET 0x04
/** This macro defines an offset into the context for use in assembly. */
#define G2_OFFSET 0x08
#define G4_OFFSET 0x08
/** This macro defines an offset into the context for use in assembly. */
#define G3_OFFSET 0x0C
#define G5_OFFSET 0x0C
/** This macro defines an offset into the context for use in assembly. */
#define G4_OFFSET 0x10
#define G6_OFFSET 0x10
/** This macro defines an offset into the context for use in assembly. */
#define G5_OFFSET 0x14
/** 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
#define O6_SP_OFFSET 0x58
/** 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
/** 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
/**