source: rtems/cpukit/score/cpu/sparc64/context.S @ 71d97c9

4.115
Last change on this file since 71d97c9 was 71d97c9, checked in by Gedare Bloom <gedare@…>, on 12/08/14 at 18:16:37

sparc64: put each copyright on one line

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/*  context.S
2 *
3 *  This file contains the basic algorithms for all assembly code used
4 *  in an specific CPU port of RTEMS.  These algorithms must be implemented
5 *  in assembly language.
6 *
7 *  COPYRIGHT (c) 1989-2007. On-Line Applications Research Corporation (OAR).
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.org/license/LICENSE.
12 *
13 *  Ported to ERC32 implementation of the SPARC by On-Line Applications
14 *  Research Corporation (OAR) under contract to the European Space
15 *  Agency (ESA).
16 *
17 *  ERC32 modifications of respective RTEMS file:
18 *  COPYRIGHT (c) 1995. European Space Agency.
19 *
20 *  Ported to UltraSPARC T1 Niagara implementation of the SPARC-v9.
21 *  Niagara modifications of respective RTEMS file:
22 *  COPYRIGHT (c) 2010. Gedare Bloom.
23 */
24
25#include <rtems/asm.h>
26
27
28/*
29 *  The assembler needs to be told that we know what to do with
30 *  the global registers.
31 */
32.register %g2, #scratch
33.register %g3, #scratch
34.register %g6, #scratch
35.register %g7, #scratch
36
37#if (SPARC_HAS_FPU == 1)
38
39/*
40 *  void _CPU_Context_save_fp(
41 *    void **fp_context_ptr
42 *  )
43 *
44 *  This routine is responsible for saving the FP context
45 *  at *fp_context_ptr.  If the point to load the FP context
46 *  from is changed then the pointer is modified by this routine.
47 *
48 */
49
50  .align 4
51PUBLIC(_CPU_Context_save_fp)
52  SYM(_CPU_Context_save_fp):
53    save    %sp, -CPU_MINIMUM_STACK_FRAME_SIZE, %sp
54
55    /*
56     *  The following enables the floating point unit.
57     */
58
59    sparc64_enable_FPU(%l0)
60
61  /*
62   *  Although sun4v supports alternate register names for double-
63   *  and quad-word floating point, SPARC v9 only uses f[#]
64   *
65   *  Because quad-word fp is not supported by the hardware in
66   *  many situations, we stick with double-word fp operations
67   */
68  ldx    [%i0], %l0     
69  std     %f0, [%l0]
70  std     %f2, [%l0 + F2_OFFSET]
71  std     %f4, [%l0 + F4_OFFSET]
72  std     %f6, [%l0 + F6_OFFSET]
73  std     %f8, [%l0 + F8_OFFSET]
74  std     %f10, [%l0 + F1O_OFFSET]
75  std     %f12, [%l0 + F12_OFFSET]
76  std     %f14, [%l0 + F14_OFFSET]
77  std     %f16, [%l0 + F16_OFFSET]
78  std     %f18, [%l0 + F18_OFFSET]
79  std     %f20, [%l0 + F2O_OFFSET]
80  std     %f22, [%l0 + F22_OFFSET]
81  std     %f24, [%l0 + F24_OFFSET]
82  std     %f26, [%l0 + F26_OFFSET]
83  std     %f28, [%l0 + F28_OFFSET]
84  std     %f30, [%l0 + F3O_OFFSET]
85  std     %f32, [%l0 + F32_OFFSET]
86  std     %f34, [%l0 + F34_OFFSET]
87  std     %f36, [%l0 + F36_OFFSET]
88  std     %f38, [%l0 + F38_OFFSET]
89  std     %f40, [%l0 + F4O_OFFSET]
90  std     %f42, [%l0 + F42_OFFSET]
91  std     %f44, [%l0 + F44_OFFSET]
92  std     %f46, [%l0 + F46_OFFSET]
93  std     %f48, [%l0 + F48_OFFSET]
94  std     %f50, [%l0 + F5O_OFFSET]
95  std     %f52, [%l0 + F52_OFFSET]
96  std     %f54, [%l0 + F54_OFFSET]
97  std     %f56, [%l0 + F56_OFFSET]
98  std     %f58, [%l0 + F58_OFFSET]
99  std     %f60, [%l0 + F6O_OFFSET]       
100  std     %f62, [%l0 + F62_OFFSET]
101  stx     %fsr, [%l0 + FSR_OFFSET]
102  ret
103  restore
104
105  /*
106   *  void _CPU_Context_restore_fp(
107   *    void **fp_context_ptr
108   *  )
109   *
110   *  This routine is responsible for restoring the FP context
111   *  at *fp_context_ptr.  If the point to load the FP context
112   *  from is changed then the pointer is modified by this routine.
113   *
114   */
115
116  .align 4
117PUBLIC(_CPU_Context_restore_fp)
118  SYM(_CPU_Context_restore_fp):
119    save    %sp, -CPU_MINIMUM_STACK_FRAME_SIZE , %sp
120
121    /*
122     *  The following enables the floating point unit.
123     */
124
125    sparc64_enable_FPU(%l0)
126
127  ldx     [%i0], %l0
128  ldd     [%l0 + FO_OFFSET], %f0
129  ldd     [%l0 + F2_OFFSET], %f2
130  ldd     [%l0 + F4_OFFSET], %f4
131  ldd     [%l0 + F6_OFFSET], %f6
132  ldd     [%l0 + F8_OFFSET], %f8
133  ldd     [%l0 + F1O_OFFSET], %f10
134  ldd     [%l0 + F12_OFFSET], %f12
135  ldd     [%l0 + F14_OFFSET], %f14
136  ldd     [%l0 + F16_OFFSET], %f16
137  ldd     [%l0 + F18_OFFSET], %f18
138  ldd     [%l0 + F2O_OFFSET], %f20
139  ldd     [%l0 + F22_OFFSET], %f22
140  ldd     [%l0 + F24_OFFSET], %f24
141  ldd     [%l0 + F26_OFFSET], %f26
142  ldd     [%l0 + F28_OFFSET], %f28
143  ldd     [%l0 + F3O_OFFSET], %f30
144  ldd     [%l0 + F32_OFFSET], %f32
145  ldd     [%l0 + F34_OFFSET], %f34
146  ldd     [%l0 + F36_OFFSET], %f36
147  ldd     [%l0 + F38_OFFSET], %f38
148  ldd     [%l0 + F4O_OFFSET], %f40
149  ldd     [%l0 + F42_OFFSET], %f42
150  ldd     [%l0 + F44_OFFSET], %f44
151  ldd     [%l0 + F46_OFFSET], %f46
152  ldd     [%l0 + F48_OFFSET], %f48
153  ldd     [%l0 + F5O_OFFSET], %f50
154  ldd     [%l0 + F52_OFFSET], %f52
155  ldd     [%l0 + F54_OFFSET], %f54
156  ldd     [%l0 + F56_OFFSET], %f56
157  ldd     [%l0 + F58_OFFSET], %f58
158  ldd     [%l0 + F6O_OFFSET], %f60
159  ldd     [%l0 + F62_OFFSET], %f62
160  ldx     [%l0 + FSR_OFFSET], %fsr
161  ret
162  restore
163
164#endif /* SPARC_HAS_FPU */
165
166  /*
167   *  void _CPU_Context_switch(
168   *    Context_Control  *run,
169   *    Context_Control  *heir
170   *  )
171   *
172   *  This routine performs a normal non-FP context switch.
173   */
174
175  .align 4
176PUBLIC(_CPU_Context_switch)
177  SYM(_CPU_Context_switch):
178    ! skip g0
179      stx     %g1, [%o0 + G1_OFFSET]       ! save the global registers
180      stx     %g2, [%o0 + G2_OFFSET]
181      stx     %g3, [%o0 + G3_OFFSET]       
182      stx     %g4, [%o0 + G4_OFFSET]
183      stx     %g5, [%o0 + G5_OFFSET]       
184      stx     %g6, [%o0 + G6_OFFSET]
185      stx     %g7, [%o0 + G7_OFFSET]
186
187      ! load the address of the ISR stack nesting prevention flag
188      setx  SYM(_CPU_ISR_Dispatch_disable), %g1, %g2
189      lduw  [%g2], %g2
190
191      ! save it a bit later so we do not waste a couple of cycles
192
193      stx     %l0, [%o0 + L0_OFFSET]       ! save the local registers
194      stx     %l1, [%o0 + L1_OFFSET]
195      stx     %l2, [%o0 + L2_OFFSET]
196      stx     %l3, [%o0 + L3_OFFSET]
197      stx     %l4, [%o0 + L4_OFFSET]
198      stx     %l5, [%o0 + L5_OFFSET]
199      stx     %l6, [%o0 + L6_OFFSET]
200      stx     %l7, [%o0 + L7_OFFSET]
201
202      ! Now actually save ISR stack nesting prevention flag
203      stuw     %g2, [%o0 + ISR_DISPATCH_DISABLE_STACK_OFFSET]
204
205      stx     %i0, [%o0 + I0_OFFSET]       ! save the input registers
206      stx     %i1, [%o0 + I1_OFFSET]
207      stx     %i2, [%o0 + I2_OFFSET]
208      stx     %i3, [%o0 + I3_OFFSET]
209      stx     %i4, [%o0 + I4_OFFSET]
210      stx     %i5, [%o0 + I5_OFFSET]
211      stx     %i6, [%o0 + I6_FP_OFFSET]
212      stx     %i7, [%o0 + I7_OFFSET]
213
214      stx     %o0, [%o0 + O0_OFFSET]       ! save the output registers
215      stx     %o1, [%o0 + O1_OFFSET]
216      stx     %o2, [%o0 + O2_OFFSET]
217      stx     %o3, [%o0 + O3_OFFSET]
218      stx     %o4, [%o0 + O4_OFFSET]
219      stx     %o5, [%o0 + O5_OFFSET]
220      stx     %o6, [%o0 + O6_SP_OFFSET]
221      stx     %o7, [%o0 + O7_OFFSET]       ! o7 is the PC
222
223!      rdpr    %pil, %o2
224!      stuw    %o2, [%o0 + PIL_OFFSET] ! save pil
225
226!      rdpr    %pstate, %o2
227!      stx     %o2, [%o0 + PSTATE_OFFSET]      ! save status register
228
229      /*
230       *  This is entered from _CPU_Context_restore with:
231       *    o1 = context to restore
232!       *    o2 = pstate
233       *
234       *  NOTE: Flushing the register windows is necessary, but it adds
235       *  an unpredictable (but bounded) overhead to context switching.
236       */
237
238PUBLIC(_CPU_Context_restore_heir)
239  SYM(_CPU_Context_restore_heir):
240
241    flushw
242
243
244
245    ! skip g0
246    ldx     [%o1 + G1_OFFSET], %g1        ! restore the global registers
247    ldx     [%o1 + G2_OFFSET], %g2
248    ldx     [%o1 + G3_OFFSET], %g3
249    ldx     [%o1 + G4_OFFSET], %g4
250    ldx     [%o1 + G5_OFFSET], %g5
251    ldx     [%o1 + G6_OFFSET], %g6
252    ldx     [%o1 + G7_OFFSET], %g7
253
254    ! Load thread specific ISR dispatch prevention flag
255    ldx    [%o1 + ISR_DISPATCH_DISABLE_STACK_OFFSET], %o2
256    setx  SYM(_CPU_ISR_Dispatch_disable), %o5, %o3
257    ! Store it to memory later to use the cycles
258
259    ldx     [%o1 + L0_OFFSET], %l0        ! restore the local registers
260    ldx     [%o1 + L1_OFFSET], %l1
261    ldx     [%o1 + L2_OFFSET], %l2
262    ldx     [%o1 + L3_OFFSET], %l3
263    ldx     [%o1 + L4_OFFSET], %l4
264    ldx     [%o1 + L5_OFFSET], %l5
265    ldx     [%o1 + L6_OFFSET], %l6
266    ldx     [%o1 + L7_OFFSET], %l7
267
268    ! Now restore thread specific ISR dispatch prevention flag
269    stuw  %o2, [%o3]
270
271    ldx     [%o1 + I0_OFFSET], %i0        ! restore the input registers
272    ldx     [%o1 + I1_OFFSET], %i1
273    ldx     [%o1 + I2_OFFSET], %i2
274    ldx     [%o1 + I3_OFFSET], %i3
275    ldx     [%o1 + I4_OFFSET], %i4
276    ldx     [%o1 + I5_OFFSET], %i5
277    ldx     [%o1 + I6_FP_OFFSET], %i6
278    ldx     [%o1 + I7_OFFSET], %i7
279
280    ldx     [%o1 + O0_OFFSET], %o0
281    ldx     [%o1 + O2_OFFSET], %o2        ! restore the output registers
282    ldx     [%o1 + O3_OFFSET], %o3
283    ldx     [%o1 + O4_OFFSET], %o4
284    ldx     [%o1 + O5_OFFSET], %o5
285    ldx     [%o1 + O6_SP_OFFSET], %o6
286    ldx     [%o1 + O7_OFFSET], %o7       ! PC
287
288    ! on a hunch... we should be able to use some of the %o regs
289!    lduw    [%o1 + PIL_OFFSET], %o2
290!    wrpr    %g0, %o2, %pil
291
292!    ldx     [%o1 + PSTATE_OFFSET], %o2
293
294    ! do o1 last to avoid destroying heir context pointer
295    ldx     [%o1 + O1_OFFSET], %o1        ! overwrite heir pointer
296!    wrpr    %g0, %o2, %pstate
297
298    retl
299    nop
300
301    /*
302     *  void _CPU_Context_restore(
303     *    Context_Control *new_context
304     *  )
305     *
306     *  This routine is generally used only to perform restart self.
307     *
308     *  NOTE: It is unnecessary to reload some registers.
309     */
310    /* if _CPU_Context_restore_heir does not flushw, then do it here */
311  .align 4
312PUBLIC(_CPU_Context_restore)
313  SYM(_CPU_Context_restore):
314    save    %sp, -CPU_MINIMUM_STACK_FRAME_SIZE, %sp
315!    rdpr    %pstate, %o2
316    ba      SYM(_CPU_Context_restore_heir)
317    mov     %i0, %o1                      ! in the delay slot
318
319/* end of file */
Note: See TracBrowser for help on using the repository browser.