source: rtems/cpukit/score/cpu/sparc/sparc-context-validate.S @ 7d7cbf3c

5
Last change on this file since 7d7cbf3c was 7d7cbf3c, checked in by Sebastian Huber <sebastian.huber@…>, on 06/06/19 at 05:53:09

sparc: Improve _CPU_Context_validate()

Use the FPU and check that the condition codes in the PSR are preserved.

Update #3756.

  • Property mode set to 100644
File size: 8.9 KB
Line 
1/*
2 * Copyright (c) 2015, 2017 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
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.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <rtems/asm.h>
20#include <rtems/score/cpuimpl.h>
21#include <rtems/score/percpu.h>
22
23#define FRAME_OFFSET_BUFFER_0 (SPARC_MINIMUM_STACK_FRAME_SIZE)
24#define FRAME_OFFSET_BUFFER_1 (FRAME_OFFSET_BUFFER_0 + 0x04)
25#define FRAME_OFFSET_BUFFER_2 (FRAME_OFFSET_BUFFER_1 + 0x04)
26#define FRAME_OFFSET_L0 (FRAME_OFFSET_BUFFER_2 + 0x04)
27#define FRAME_OFFSET_L1 (FRAME_OFFSET_L0 + 0x04)
28#define FRAME_OFFSET_L2 (FRAME_OFFSET_L1 + 0x04)
29#define FRAME_OFFSET_L3 (FRAME_OFFSET_L2 + 0x04)
30#define FRAME_OFFSET_L4 (FRAME_OFFSET_L3 + 0x04)
31#define FRAME_OFFSET_L5 (FRAME_OFFSET_L4 + 0x04)
32#define FRAME_OFFSET_L6 (FRAME_OFFSET_L5 + 0x04)
33#define FRAME_OFFSET_L7 (FRAME_OFFSET_L6 + 0x04)
34#define FRAME_OFFSET_I0 (FRAME_OFFSET_L7 + 0x04)
35#define FRAME_OFFSET_I1 (FRAME_OFFSET_I0 + 0x04)
36#define FRAME_OFFSET_I2 (FRAME_OFFSET_I1 + 0x04)
37#define FRAME_OFFSET_I3 (FRAME_OFFSET_I2 + 0x04)
38#define FRAME_OFFSET_I4 (FRAME_OFFSET_I3 + 0x04)
39#define FRAME_OFFSET_I5 (FRAME_OFFSET_I4 + 0x04)
40#define FRAME_OFFSET_I6 (FRAME_OFFSET_I5 + 0x04)
41#define FRAME_OFFSET_I7 (FRAME_OFFSET_I6 + 0x04)
42#define FRAME_END (FRAME_OFFSET_I7 + 0x04)
43#define FRAME_SIZE \
44  ((FRAME_END + CPU_STACK_ALIGNMENT - 1) & ~(CPU_STACK_ALIGNMENT - 1))
45
46/*
47 * The FSR pattern is masked with undefined fields, reserved fields, ftt
48 * (cleared by fmovs), cexc (cleared by fmovs), and system-specific values
49 * (e.g. FPU architecture version, FP queue).
50 */
51#define FSR_PATTERN_MASK 0xcf800fe0
52
53.macro check_register reg
54        sub     %g1, 1, %g1
55        cmp     %g1, \reg
56        bne     restore_registers
57         nop
58.endm
59
60.macro check_float_register reg
61        sub     %g1, 1, %g1
62        st      \reg, [%sp + FRAME_OFFSET_BUFFER_0]
63        cmp     %g0, %sp
64        fmovs   \reg, \reg
65        be      restore_registers
66         nop
67        cmp     %g0, %g0
68        fmovs   \reg, \reg
69        bne     restore_registers
70         nop
71        ld      [%sp + FRAME_OFFSET_BUFFER_0], %o1
72        cmp     %g1, %o1
73        bne     restore_registers
74         nop
75.endm
76
77.macro write_register reg
78        add     %g1, 1, %g1
79        mov     %g1, \reg
80.endm
81
82.macro write_float_register reg
83        add     %g1, 1, %g1
84        st      %g1, [%sp + FRAME_OFFSET_BUFFER_0]
85        ld      [%sp + FRAME_OFFSET_BUFFER_0], \reg
86.endm
87
88        .align 4
89        PUBLIC(_CPU_Context_validate)
90SYM(_CPU_Context_validate):
91
92        /* g2 indicates if the FPU should be checked */
93#if defined(SPARC_USE_LAZY_FP_SWITCH)
94        ld      [%g6 + PER_CPU_OFFSET_EXECUTING], %g2
95        ld      [%g2 + %lo(SPARC_THREAD_CONTROL_FP_CONTEXT_OFFSET)], %g2
96#else
97        mov     %psr, %g2
98        sethi   %hi(SPARC_PSR_EF_MASK), %g3
99        and     %g2, %g3, %g2
100#endif
101
102        /* g1 is used to save the original pattern */
103        mov     %o0, %g1
104
105        /* g4 establishes window counter */
106        clr     %g4
107
108        add     %sp, -FRAME_SIZE, %sp
109
110        st      %l0, [%sp + FRAME_OFFSET_L0]
111        st      %l1, [%sp + FRAME_OFFSET_L1]
112        st      %l2, [%sp + FRAME_OFFSET_L2]
113        st      %l3, [%sp + FRAME_OFFSET_L3]
114        st      %l4, [%sp + FRAME_OFFSET_L4]
115        st      %l5, [%sp + FRAME_OFFSET_L5]
116        st      %l6, [%sp + FRAME_OFFSET_L6]
117        st      %l7, [%sp + FRAME_OFFSET_L7]
118        st      %i0, [%sp + FRAME_OFFSET_I0]
119        st      %i1, [%sp + FRAME_OFFSET_I1]
120        st      %i2, [%sp + FRAME_OFFSET_I2]
121        st      %i3, [%sp + FRAME_OFFSET_I3]
122        st      %i4, [%sp + FRAME_OFFSET_I4]
123        st      %i5, [%sp + FRAME_OFFSET_I5]
124        st      %i6, [%sp + FRAME_OFFSET_I6]
125        st      %i7, [%sp + FRAME_OFFSET_I7]
126
127        cmp     %g4, 0
128        bne     write_locals_and_outputs
129         nop
130        be      check_for_fp
131         nop
132
133new_check_cycle:
134        clr     %g4
135        add     %g4, 1, %g4
136        ld      [%sp + FRAME_OFFSET_BUFFER_1], %g1
137        b       switch_to_next_window
138         nop
139        /* Write pattern values into registers */
140
141check_for_fp:
142        cmp     %g2, 0
143        be      write_y
144         nop
145
146        /* Write masked pattern to FSR */
147        st      %fsr, [%sp + FRAME_OFFSET_BUFFER_0]
148        ld      [%sp + FRAME_OFFSET_BUFFER_0], %o1
149        add     %g1, 1, %g1
150        sethi   %hi(FSR_PATTERN_MASK), %g3
151        or      %g3, %lo(FSR_PATTERN_MASK), %g3
152        and     %g1, %g3, %g3
153        or      %o1, %g3, %g3
154        st      %g3, [%sp + FRAME_OFFSET_BUFFER_0]
155        ld      [%sp + FRAME_OFFSET_BUFFER_0], %fsr
156
157        write_float_register    %f0
158        write_float_register    %f1
159        write_float_register    %f2
160        write_float_register    %f3
161        write_float_register    %f4
162        write_float_register    %f5
163        write_float_register    %f6
164        write_float_register    %f7
165        write_float_register    %f8
166        write_float_register    %f9
167        write_float_register    %f10
168        write_float_register    %f11
169        write_float_register    %f12
170        write_float_register    %f13
171        write_float_register    %f14
172        write_float_register    %f15
173        write_float_register    %f16
174        write_float_register    %f17
175        write_float_register    %f18
176        write_float_register    %f19
177        write_float_register    %f20
178        write_float_register    %f21
179        write_float_register    %f22
180        write_float_register    %f23
181        write_float_register    %f24
182        write_float_register    %f25
183        write_float_register    %f26
184        write_float_register    %f27
185        write_float_register    %f28
186        write_float_register    %f29
187        write_float_register    %f30
188        write_float_register    %f31
189
190write_y:
191        write_register  %y
192
193        write_register  %i0
194        write_register  %i1
195        write_register  %i2
196        write_register  %i3
197        write_register  %i4
198        write_register  %i5
199        /* Don't write register $i6 => frame pointer */
200        /* Don't write register $i7 => return address */
201        b       write_locals_and_outputs
202         nop
203
204switch_to_next_window:
205        save    %sp, -FRAME_SIZE, %sp
206
207write_locals_and_outputs:
208        /* l0 is used as a scratch register */
209        write_register  %l1
210        write_register  %l2
211        write_register  %l3
212        write_register  %l4
213        write_register  %l5
214        write_register  %l6
215        write_register  %l7
216        write_register  %o1
217        write_register  %o2
218        write_register  %o3
219        write_register  %o4
220        write_register  %o5
221        /* Don't write register $o6 => stack pointer */
222        /* Don't write register $o7 => return address */
223
224        add     %g4, 1, %g4
225        cmp     %g4, 1
226        bne     no_store
227         nop
228        st      %g1, [%sp + FRAME_OFFSET_BUFFER_1]
229
230no_store:
231        cmp     %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
232        bne     switch_to_next_window
233         nop
234
235        /* Dummy increment to set up reverse mechanism for checking process */
236        add     %g1, 1, %g1
237        clr     %g4
238
239        /* Checking begins here */
240window_checking:
241        cmp     %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
242        be      y_checking
243         nop
244
245further_checking:
246        cmp     %g4, 0
247        bne     goto_local_registers
248         nop
249
250        /* Check normal registers */
251        check_register  %o5
252        check_register  %o4
253        check_register  %o3
254        check_register  %o2
255        check_register  %o1
256
257goto_local_registers:
258        check_register  %l7
259        check_register  %l6
260        check_register  %l5
261        check_register  %l4
262        check_register  %l3
263        check_register  %l2
264        check_register  %l1
265
266        check_register  %i5
267        check_register  %i4
268        check_register  %i3
269        check_register  %i2
270        check_register  %i1
271        /*
272        For the last window i0 also needs to be checked as this variable
273        is not overwritten by the outputs of another window.
274        */
275        add     %g4, 1, %g4
276        cmp     %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS
277        bne     dont_check_i0
278         nop
279        check_register  %i0
280        b       y_checking
281         nop
282
283dont_check_i0:
284        restore
285
286        ba      window_checking
287         nop
288
289        /* Check Y register */
290y_checking:
291        st      %o1, [%sp + FRAME_OFFSET_BUFFER_2]
292        mov     %y, %o1
293        check_register  %o1
294        ld      [%sp + FRAME_OFFSET_BUFFER_2], %o1
295        cmp     %g2, 0
296        be      new_check_cycle
297         nop
298
299        st      %o1, [%sp + FRAME_OFFSET_BUFFER_2]
300        SPARC_LEON3FT_B2BST_NOP
301        /* Check floating point registers */
302        check_float_register    %f31
303        check_float_register    %f30
304        check_float_register    %f29
305        check_float_register    %f28
306        check_float_register    %f27
307        check_float_register    %f26
308        check_float_register    %f25
309        check_float_register    %f24
310        check_float_register    %f23
311        check_float_register    %f22
312        check_float_register    %f21
313        check_float_register    %f20
314        check_float_register    %f19
315        check_float_register    %f18
316        check_float_register    %f17
317        check_float_register    %f16
318        check_float_register    %f15
319        check_float_register    %f14
320        check_float_register    %f13
321        check_float_register    %f12
322        check_float_register    %f11
323        check_float_register    %f10
324        check_float_register    %f9
325        check_float_register    %f8
326        check_float_register    %f7
327        check_float_register    %f6
328        check_float_register    %f5
329        check_float_register    %f4
330        check_float_register    %f3
331        check_float_register    %f2
332        check_float_register    %f1
333        check_float_register    %f0
334
335        st      %fsr, [%sp + FRAME_OFFSET_BUFFER_0]
336        ld      [%sp + FRAME_OFFSET_BUFFER_0], %o1
337        sub     %g1, 1, %g1
338        clr     %g3
339        sethi   %hi(FSR_PATTERN_MASK), %g3
340        or      %g3, %lo(FSR_PATTERN_MASK), %g3
341        and     %g1, %g3, %g3
342        and     %o1, %g3, %o1
343        cmp     %o1, %g3
344        bne     restore_registers
345         ld     [%sp + FRAME_OFFSET_BUFFER_2], %o1
346
347        b       new_check_cycle
348         nop
349
350        /****** RESTORE STARTS HERE *******/
351
352        /* Restore non-volatile registers */
353
354restore_registers:
355        and     %g4, (SPARC_NUMBER_OF_REGISTER_WINDOWS - 1), %g4
356        cmp     %g4, 0
357        be      real_restore
358         nop
359        restore
360        sub     %g4, 1, %g4
361        bne     restore_registers
362         nop
363
364real_restore:
365        ld      [%sp + FRAME_OFFSET_L0], %l0
366        ld      [%sp + FRAME_OFFSET_L1], %l1
367        ld      [%sp + FRAME_OFFSET_L2], %l2
368        ld      [%sp + FRAME_OFFSET_L3], %l3
369        ld      [%sp + FRAME_OFFSET_L4], %l4
370        ld      [%sp + FRAME_OFFSET_L5], %l5
371        ld      [%sp + FRAME_OFFSET_L6], %l6
372        ld      [%sp + FRAME_OFFSET_L7], %l7
373        ld      [%sp + FRAME_OFFSET_I0], %i0
374        ld      [%sp + FRAME_OFFSET_I1], %i1
375        ld      [%sp + FRAME_OFFSET_I2], %i2
376        ld      [%sp + FRAME_OFFSET_I3], %i3
377        ld      [%sp + FRAME_OFFSET_I4], %i4
378        ld      [%sp + FRAME_OFFSET_I5], %i5
379        ld      [%sp + FRAME_OFFSET_I6], %i6
380        ld      [%sp + FRAME_OFFSET_I7], %i7
381
382        sub     %sp, -FRAME_SIZE, %sp
383
384return_value:
385        /* Load callback address and jump back */
386        jmp     %o7 + 8
387         add    %sp, FRAME_SIZE, %sp
Note: See TracBrowser for help on using the repository browser.