Linux-libre 5.4.49-gnu
[librecmc/linux-libre.git] / arch / sh / kernel / cpu / sh5 / switchto.S
1 /* SPDX-License-Identifier: GPL-2.0
2  *
3  * arch/sh/kernel/cpu/sh5/switchto.S
4  *
5  * sh64 context switch
6  *
7  * Copyright (C) 2004  Richard Curnow
8 */
9
10         .section .text..SHmedia32,"ax"
11         .little
12
13         .balign 32
14
15         .type sh64_switch_to,@function
16         .global sh64_switch_to
17         .global __sh64_switch_to_end
18 sh64_switch_to:
19
20 /* Incoming args
21    r2 - prev
22    r3 - &prev->thread
23    r4 - next
24    r5 - &next->thread
25
26    Outgoing results
27    r2 - last (=prev) : this just stays in r2 throughout
28
29    Want to create a full (struct pt_regs) on the stack to allow backtracing
30    functions to work.  However, we only need to populate the callee-save
31    register slots in this structure; since we're a function our ancestors must
32    have themselves preserved all caller saved state in the stack.  This saves
33    some wasted effort since we won't need to look at the values.
34
35    In particular, all caller-save registers are immediately available for
36    scratch use.
37
38 */
39
40 #define FRAME_SIZE (76*8 + 8)
41
42         movi    FRAME_SIZE, r0
43         sub.l   r15, r0, r15
44         ! Do normal-style register save to support backtrace
45
46         st.l    r15,   0, r18   ! save link reg
47         st.l    r15,   4, r14   ! save fp
48         add.l   r15, r63, r14   ! setup frame pointer
49
50         ! hopefully this looks normal to the backtrace now.
51
52         addi.l  r15,   8, r1    ! base of pt_regs
53         addi.l  r1,   24, r0    ! base of pt_regs.regs
54         addi.l  r0, (63*8), r8  ! base of pt_regs.trregs
55
56         /* Note : to be fixed?
57            struct pt_regs is really designed for holding the state on entry
58            to an exception, i.e. pc,sr,regs etc.  However, for the context
59            switch state, some of this is not required.  But the unwinder takes
60            struct pt_regs * as an arg so we have to build this structure
61            to allow unwinding switched tasks in show_state() */
62
63         st.q    r0, ( 9*8), r9
64         st.q    r0, (10*8), r10
65         st.q    r0, (11*8), r11
66         st.q    r0, (12*8), r12
67         st.q    r0, (13*8), r13
68         st.q    r0, (14*8), r14 ! for unwind, want to look as though we took a trap at
69         ! the point where the process is left in suspended animation, i.e. current
70         ! fp here, not the saved one.
71         st.q    r0, (16*8), r16
72
73         st.q    r0, (24*8), r24
74         st.q    r0, (25*8), r25
75         st.q    r0, (26*8), r26
76         st.q    r0, (27*8), r27
77         st.q    r0, (28*8), r28
78         st.q    r0, (29*8), r29
79         st.q    r0, (30*8), r30
80         st.q    r0, (31*8), r31
81         st.q    r0, (32*8), r32
82         st.q    r0, (33*8), r33
83         st.q    r0, (34*8), r34
84         st.q    r0, (35*8), r35
85
86         st.q    r0, (44*8), r44
87         st.q    r0, (45*8), r45
88         st.q    r0, (46*8), r46
89         st.q    r0, (47*8), r47
90         st.q    r0, (48*8), r48
91         st.q    r0, (49*8), r49
92         st.q    r0, (50*8), r50
93         st.q    r0, (51*8), r51
94         st.q    r0, (52*8), r52
95         st.q    r0, (53*8), r53
96         st.q    r0, (54*8), r54
97         st.q    r0, (55*8), r55
98         st.q    r0, (56*8), r56
99         st.q    r0, (57*8), r57
100         st.q    r0, (58*8), r58
101         st.q    r0, (59*8), r59
102
103         ! do this early as pta->gettr has no pipeline forwarding (=> 5 cycle latency)
104         ! Use a local label to avoid creating a symbol that will confuse the !
105         ! backtrace
106         pta     .Lsave_pc, tr0
107
108         gettr   tr5, r45
109         gettr   tr6, r46
110         gettr   tr7, r47
111         st.q    r8, (5*8), r45
112         st.q    r8, (6*8), r46
113         st.q    r8, (7*8), r47
114
115         ! Now switch context
116         gettr   tr0, r9
117         st.l    r3, 0, r15      ! prev->thread.sp
118         st.l    r3, 8, r1       ! prev->thread.kregs
119         st.l    r3, 4, r9       ! prev->thread.pc
120         st.q    r1, 0, r9       ! save prev->thread.pc into pt_regs->pc
121
122         ! Load PC for next task (init value or save_pc later)
123         ld.l    r5, 4, r18      ! next->thread.pc
124         ! Switch stacks
125         ld.l    r5, 0, r15      ! next->thread.sp
126         ptabs   r18, tr0
127
128         ! Update current
129         ld.l    r4, 4, r9       ! next->thread_info (2nd element of next task_struct)
130         putcon  r9, kcr0        ! current = next->thread_info
131
132         ! go to save_pc for a reschedule, or the initial thread.pc for a new process
133         blink   tr0, r63
134
135         ! Restore (when we come back to a previously saved task)
136 .Lsave_pc:
137         addi.l  r15, 32, r0     ! r0 = next's regs
138         addi.l  r0, (63*8), r8  ! r8 = next's tr_regs
139
140         ld.q    r8, (5*8), r45
141         ld.q    r8, (6*8), r46
142         ld.q    r8, (7*8), r47
143         ptabs   r45, tr5
144         ptabs   r46, tr6
145         ptabs   r47, tr7
146
147         ld.q    r0, ( 9*8), r9
148         ld.q    r0, (10*8), r10
149         ld.q    r0, (11*8), r11
150         ld.q    r0, (12*8), r12
151         ld.q    r0, (13*8), r13
152         ld.q    r0, (14*8), r14
153         ld.q    r0, (16*8), r16
154
155         ld.q    r0, (24*8), r24
156         ld.q    r0, (25*8), r25
157         ld.q    r0, (26*8), r26
158         ld.q    r0, (27*8), r27
159         ld.q    r0, (28*8), r28
160         ld.q    r0, (29*8), r29
161         ld.q    r0, (30*8), r30
162         ld.q    r0, (31*8), r31
163         ld.q    r0, (32*8), r32
164         ld.q    r0, (33*8), r33
165         ld.q    r0, (34*8), r34
166         ld.q    r0, (35*8), r35
167
168         ld.q    r0, (44*8), r44
169         ld.q    r0, (45*8), r45
170         ld.q    r0, (46*8), r46
171         ld.q    r0, (47*8), r47
172         ld.q    r0, (48*8), r48
173         ld.q    r0, (49*8), r49
174         ld.q    r0, (50*8), r50
175         ld.q    r0, (51*8), r51
176         ld.q    r0, (52*8), r52
177         ld.q    r0, (53*8), r53
178         ld.q    r0, (54*8), r54
179         ld.q    r0, (55*8), r55
180         ld.q    r0, (56*8), r56
181         ld.q    r0, (57*8), r57
182         ld.q    r0, (58*8), r58
183         ld.q    r0, (59*8), r59
184
185         ! epilogue
186         ld.l    r15, 0, r18
187         ld.l    r15, 4, r14
188         ptabs   r18, tr0
189         movi    FRAME_SIZE, r0
190         add     r15, r0, r15
191         blink   tr0, r63
192 __sh64_switch_to_end:
193 .LFE1:
194         .size   sh64_switch_to,.LFE1-sh64_switch_to
195