source: rtems/c/src/lib/libcpu/sparc/reg_win/window.S @ c193baad

4.104.11
Last change on this file since c193baad was 359e537, checked in by Ralf Corsepius <ralf.corsepius@…>, on Nov 30, 2009 at 5:09:41 AM

Whitespace removal.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 *  window.s
3 *
4 *  This file contains the register window management routines for the
5 *  SPARC architecture.  Trap handlers for the following capabilities
6 *  are included in this file:
7 *
8 *    + Window Overflow
9 *    + Window Underflow
10 *    + Flushing All Windows
11 *
12 *  COPYRIGHT:
13 *
14 *  This file includes the window overflow and underflow handlers from
15 *  the file srt0.s provided with the binary distribution of the SPARC
16 *  Instruction Simulator (SIS) found at
17 *  ftp://ftp.estec.esa.nl/pub/ws/wsd/erc32.
18 *
19 *  COPYRIGHT (c) 1995. European Space Agency.
20 *
21 *  This terms of the RTEMS license apply to this file.
22 *
23 *  $Id$
24 */
25
26#include <rtems/asm.h>
27
28        .seg    "text"
29        /*
30         *  Window overflow trap handler.
31         *
32         *  On entry:
33         *
34         *    l0 = psr (from trap table)
35         *    l1 = pc
36         *    l2 = npc
37         */
38
39        PUBLIC(window_overflow_trap_handler)
40
41SYM(window_overflow_trap_handler):
42
43        /*
44         *  Calculate new WIM by "rotating" the valid bits in the WIM right
45         *  by one position.  The following shows how the bits move for a SPARC
46         *  cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8.
47         *
48         *    OLD WIM = 76543210
49         *    NEW WIM = 07654321
50         *
51         *  NOTE: New WIM must be stored in a global register since the
52         *        "save" instruction just prior to the load of the wim
53         *        register will result in the local register set changing.
54         */
55
56        mov  %wim, %l3                   ! l3 = WIM
57        mov  %g1, %l7                    ! save g1
58        srl  %l3, 1, %g1                 ! g1 = WIM >> 1
59        sll  %l3, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l4
60                                         ! l4 = WIM << (Number Windows - 1)
61        or   %l4, %g1, %g1               ! g1 = (WIM >> 1) |
62                                         !      (WIM << (Number Windows - 1))
63
64        save                             ! Get into window to be saved.
65        mov  %g1, %wim                   ! load new WIM
66        nop; nop; nop                    ! 3 slot delay
67        std  %l0, [%sp + 0x00]           ! save local register set
68        std  %l2, [%sp + 0x08]
69        std  %l4, [%sp + 0x10]
70        std  %l6, [%sp + 0x18]
71        std  %i0, [%sp + 0x20]           ! save input register set
72        std  %i2, [%sp + 0x28]
73        std  %i4, [%sp + 0x30]
74        std  %i6, [%sp + 0x38]
75        restore                          ! Go back to trap window.
76        mov  %l7, %g1                    ! restore g1
77        jmp  %l1                         ! Re-execute save.
78        rett %l2
79
80        /*
81         *  Window underflow trap handler.
82         *
83         *  On entry:
84         *
85         *    l0 = psr (from trap table)
86         *    l1 = pc
87         *    l2 = npc
88         */
89
90        PUBLIC(window_underflow_trap_handler)
91
92SYM(window_underflow_trap_handler):
93
94        /*
95         *  Calculate new WIM by "rotating" the valid bits in the WIM left
96         *  by one position.  The following shows how the bits move for a SPARC
97         *  cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8.
98         *
99         *    OLD WIM = 76543210
100         *    NEW WIM = 07654321
101         *
102         *  NOTE: New WIM must be stored in a global register since the
103         *        "save" instruction just prior to the load of the wim
104         *        register will result in the local register set changing.
105         */
106
107        mov  %wim, %l3                  ! Calculate new WIM
108        sll  %l3, 1, %l4                ! l4 = WIM << 1
109        srl  %l3, SPARC_NUMBER_OF_REGISTER_WINDOWS-1, %l5
110                                        ! l5 = WIM >> (Number Windows-1)
111        or   %l5, %l4, %l5              ! l5 = (WIM << 1) |
112                                        !      (WIM >> (Number Windows-1))
113        mov  %l5, %wim                  ! load the new WIM
114        nop; nop; nop
115        restore                         ! Two restores to get into the
116        restore                         ! window to restore
117        ldd  [%sp + 0x00], %l0          ! First the local register set
118        ldd  [%sp + 0x08], %l2
119        ldd  [%sp + 0x10], %l4
120        ldd  [%sp + 0x18], %l6
121        ldd  [%sp + 0x20], %i0          ! Then the input registers
122        ldd  [%sp + 0x28], %i2
123        ldd  [%sp + 0x30], %i4
124        ldd  [%sp + 0x38], %i6
125        save                            ! Get back to the trap window.
126        save
127        jmp  %l1                        ! Re-execute restore.
128        rett  %l2
129
130        /*
131         *  Flush All Windows trap handler.
132         *
133         *  Flush all windows with valid contents except the current one
134         *  and the one we will be returning to.
135         *
136         *  In examining the set register windows, one may logically divide
137         *  the windows into sets (some of which may be empty) based on their
138         *  current status:
139         *
140         *    + current (i.e. in use),
141         *    + used (i.e. a restore would not trap)
142         *    + invalid (i.e. 1 in corresponding bit in WIM)
143         *    + unused
144         *
145         *  Either the used or unused set of windows may be empty.
146         *
147         *  NOTE: We assume only one bit is set in the WIM at a time.
148         *
149         *  Given a CWP of 5 and a WIM of 0x1, the registers are divided
150         *  into sets as follows:
151         *
152         *    + 0   - invalid
153         *    + 1-4 - unused
154         *    + 5   - current
155         *    + 6-7 - used
156         *
157         *  In this case, we only would save the used windows which we
158         *  will not be returning to -- 6.
159         *
160         *    Register Usage while saving the windows:
161         *      g1 = current PSR
162         *      g2 = current wim
163         *      g3 = CWP
164         *      g4 = wim scratch
165         *      g5 = scratch
166         *
167         *  On entry:
168         *
169         *    l0 = psr (from trap table)
170         *    l1 = pc
171         *    l2 = npc
172         */
173
174        PUBLIC(window_flush_trap_handler)
175
176SYM(window_flush_trap_handler):
177        /*
178         *  Save the global registers we will be using
179         */
180
181        mov     %g1, %l3
182        mov     %g2, %l4
183        mov     %g3, %l5
184        mov     %g4, %l6
185        mov     %g5, %l7
186
187        mov     %l0, %g1                      ! g1 = psr
188        mov     %wim, %g2                     ! g2 = wim
189        and     %l0, SPARC_PSR_CWP_MASK, %g3  ! g3 = CWP
190
191        add     %g3, 1, %g5                   ! g5 = CWP + 1
192        and     %g5, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g5
193
194        mov     1, %g4
195        sll     %g4, %g5, %g4                 ! g4 = WIM mask for CWP+1 invalid
196
197        restore                               ! go back one register window
198
199save_frame_loop:
200        sll     %g4, 1, %g5                   ! rotate the "wim" left 1
201        srl     %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4
202        or      %g4, %g5, %g4                 ! g4 = wim if we do one restore
203
204        /*
205         *  If a restore would not underflow, then continue.
206         */
207
208        andcc   %g4, %g2, %g0                 ! Any windows to flush?
209        bnz     done_flushing                 ! No, then continue
210        nop
211
212        restore                               ! back one window
213
214        /*
215         *  Now save the window just as if we overflowed to it.
216         */
217
218        std     %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET]
219        std     %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET]
220        std     %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET]
221        std     %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET]
222
223        std     %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET]
224        std     %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET]
225        std     %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET]
226        std     %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET]
227
228        ba      save_frame_loop
229        nop
230
231done_flushing:
232
233        add     %g3, 2, %g3                   ! calculate desired WIM
234        and     %g3, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g3
235        mov     1, %g4
236        sll     %g4, %g3, %g4                 ! g4 = new WIM
237        mov     %g4, %wim
238
239        mov     %g1, %psr                     ! restore PSR
240        nop
241        nop
242        nop
243
244        /*
245         *  Restore the global registers we used
246         */
247
248        mov     %l3, %g1
249        mov     %l4, %g2
250        mov     %l5, %g3
251        mov     %l6, %g4
252        mov     %l7, %g5
253
254        jmpl    %l2, %g0
255        rett    %l2 + 4
256
257/* end of file */
Note: See TracBrowser for help on using the repository browser.