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

4.115
Last change on this file since c86da31c was c86da31c, checked in by Joel Sherrill <joel.sherrill@…>, on 06/15/10 at 22:43:56

2010-06-15 Joel Sherrill <joel.sherrill@…>

PR 1561/cpukit

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