Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / sparc32 / switch.S
1 #define __ASSEMBLY
2 #include "psr.h"
3 #include "asm/asi.h"
4 #define ASI_BP ASI_M_BYPASS
5 #define REGWIN_SZ   0x40
6
7         .globl  __switch_context, __switch_context_nosave, __exit_context, halt
8
9         .text
10         .align  4
11
12 #define STACKFRAME_SZ     0x60
13
14 /* These are just handy. */
15 #define _SV     save    %sp, -STACKFRAME_SZ, %sp
16 #define _RS     restore
17
18 #define FLUSH_ALL_KERNEL_WINDOWS \
19         _SV; _SV; _SV; _SV; _SV; _SV; _SV; \
20         _RS; _RS; _RS; _RS; _RS; _RS; _RS;
21
22 /*
23  * Switch execution context
24  * This saves registers in the stack, then
25  * switches the stack, and restores everything from the new stack.
26  * This function takes no argument. New stack pointer is
27  * taken from global variable __context, and old stack pointer
28  * is also saved to __context. This way we can just jump to
29  * this routine to get back to the original context.
30  */
31
32 __switch_context:
33         FLUSH_ALL_KERNEL_WINDOWS
34         /* Save everything in stack */
35         st      %fp, [%fp + 120 -144]
36         add     %fp, -144, %fp
37         st      %g1, [%fp + 4]
38         st      %g2, [%fp + 8]
39         st      %g3, [%fp + 12]
40         st      %g4, [%fp + 16]
41         st      %g5, [%fp + 20]
42         st      %g6, [%fp + 24]
43         st      %g7, [%fp + 28]
44
45         st      %o0, [%fp + 32]
46         st      %o1, [%fp + 36]
47         st      %o2, [%fp + 40]
48         st      %o3, [%fp + 44]
49         st      %o4, [%fp + 48]
50         st      %o5, [%fp + 52]
51         st      %sp, [%fp + 56]
52         st      %o7, [%fp + 60]
53
54         st      %l0, [%fp + 64]
55         st      %l1, [%fp + 68]
56         st      %l2, [%fp + 72]
57         st      %l3, [%fp + 76]
58         st      %l4, [%fp + 80]
59         st      %l5, [%fp + 84]
60         st      %l6, [%fp + 88]
61         st      %l7, [%fp + 92]
62
63         st      %i0, [%fp + 96]
64         st      %i1, [%fp + 100]
65         st      %i2, [%fp + 104]
66         st      %i3, [%fp + 108]
67         st      %i4, [%fp + 112]
68         st      %i5, [%fp + 116]
69         st      %i7, [%fp + 124]
70
71         /* ctx->return_address:  Return to caller */
72         st      %o7, [%fp + 128]
73
74         /* Interrupts are not allowed... */
75
76         /* Turn on Supervisor, EnableFloating, and all the PIL bits.
77          * Also puts us in register window zero with traps off.
78          */
79 #if 0
80         set     (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
81         wr      %g2, 0x0, %psr
82 #endif
83         set     __context, %g1
84         /* Swap ctx pointer with %fp and jump*/
85         ba     __set_context
86          swap      [%g1], %fp
87 __switch_context_nosave:
88         set     __context, %g1
89         /* load %fp from ctx pointer */
90         ld      [%g1], %fp
91 __set_context:
92         /* Load all registers */
93         /* offset 0: %g0, no need to load */
94         ld      [%fp + 4], %g1
95         ld      [%fp + 8], %g2
96         ld      [%fp + 12], %g3
97         ld      [%fp + 16], %g4
98         ld      [%fp + 20], %g5
99         ld      [%fp + 24], %g6
100         ld      [%fp + 28], %g7
101
102         /* offset 32: %o0, loaded from ctx->param */
103         ld      [%fp + 36], %o1
104         ld      [%fp + 40], %o2
105         ld      [%fp + 44], %o3
106         ld      [%fp + 48], %o4
107         ld      [%fp + 52], %o5
108         ld      [%fp + 56], %sp
109         /* offset 60: %o7, loaded from ctx->return_addr */
110
111         ld      [%fp + 64], %l0
112         ld      [%fp + 68], %l1
113         ld      [%fp + 72], %l2
114         ld      [%fp + 76], %l3
115         ld      [%fp + 80], %l4
116         ld      [%fp + 84], %l5
117         ld      [%fp + 88], %l6
118         ld      [%fp + 92], %l7
119
120         ld      [%fp + 96], %i0
121         ld      [%fp + 100], %i1
122         ld      [%fp + 104], %i2
123         ld      [%fp + 108], %i3
124         ld      [%fp + 112], %i4
125         ld      [%fp + 116], %i5
126         ld      [%fp + 124], %i7
127
128         /* ctx->return_addr */
129         ld      [%fp + 136], %o7
130
131         /* ctx->param */
132         ld      [%fp + 140], %o0
133
134         /* ctx->pc, save %g1 to %y and load to %g1 */
135         mov     %g1, %y
136         ld      [%fp + 128], %g1
137         /* %fp last */
138         ld      [%fp + 120], %fp
139         /* Finally, get the new %pc from %g1 and restore %g1*/
140         jmp     %g1
141          mov    %y, %g1
142
143         FLUSH_ALL_KERNEL_WINDOWS
144 __exit_context:
145         /* Get back to the original context */
146         call    __switch_context
147          nop
148
149         /* We get here if the other context attempt to switch to this
150          * dead context. This should not happen. */
151
152 halt:
153         b       halt
154          nop