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