Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / arch / frv / kernel / switch_to.S
1 ###############################################################################
2 #
3 # switch_to.S: context switch operation
4 #
5 # Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
6 # Written by David Howells (dhowells@redhat.com)
7 #
8 # This program is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU General Public License
10 # as published by the Free Software Foundation; either version
11 # 2 of the License, or (at your option) any later version.
12 #
13 ###############################################################################
14
15 #include <linux/linkage.h>
16 #include <asm/thread_info.h>
17 #include <asm/processor.h>
18 #include <asm/registers.h>
19 #include <asm/spr-regs.h>
20
21 .macro LEDS val
22         setlos          #~\val,gr27
23         st              gr27,@(gr30,gr0)
24         membar
25         dcf             @(gr30,gr0)
26 .endm
27
28         .section        .sdata
29         .balign         8
30
31         # address of frame 0 (userspace) on current kernel stack
32         .globl          __kernel_frame0_ptr
33 __kernel_frame0_ptr:
34         .long           init_thread_union + THREAD_SIZE - FRV_FRAME0_SIZE
35
36         # address of current task
37         .globl          __kernel_current_task
38 __kernel_current_task:
39         .long           init_task
40
41         .section        .text
42         .balign         4
43
44 ###############################################################################
45 #
46 # struct task_struct *__switch_to(struct thread_struct *prev_thread,
47 #                                 struct thread_struct *next_thread,
48 #                                 struct task_struct *prev)
49 #
50 ###############################################################################
51         .globl          __switch_to
52 __switch_to:
53         # save outgoing process's context
54         sethi.p         %hi(__switch_back),gr13
55         setlo           %lo(__switch_back),gr13
56         movsg           lr,gr12
57
58         stdi            gr28,@(gr8,#__THREAD_FRAME)
59         sti             sp  ,@(gr8,#__THREAD_SP)
60         sti             fp  ,@(gr8,#__THREAD_FP)
61         stdi            gr12,@(gr8,#__THREAD_LR)
62         stdi            gr16,@(gr8,#__THREAD_GR(16))
63         stdi            gr18,@(gr8,#__THREAD_GR(18))
64         stdi            gr20,@(gr8,#__THREAD_GR(20))
65         stdi            gr22,@(gr8,#__THREAD_GR(22))
66         stdi            gr24,@(gr8,#__THREAD_GR(24))
67         stdi.p          gr26,@(gr8,#__THREAD_GR(26))
68
69         or              gr8,gr8,gr22
70         ldi.p           @(gr8,#__THREAD_USER),gr8
71         call            save_user_regs
72         or              gr22,gr22,gr8
73         
74         # retrieve the new context
75         sethi.p         %hi(__kernel_frame0_ptr),gr6
76         setlo           %lo(__kernel_frame0_ptr),gr6
77         movsg           psr,gr4
78
79         lddi.p          @(gr9,#__THREAD_FRAME),gr10
80         or              gr10,gr10,gr27          ; save prev for the return value
81
82         ldi             @(gr11,#4),gr19         ; get new_current->thread_info
83
84         lddi            @(gr9,#__THREAD_SP),gr12
85         ldi             @(gr9,#__THREAD_LR),gr14
86         ldi             @(gr9,#__THREAD_PC),gr18
87         ldi.p           @(gr9,#__THREAD_FRAME0),gr7
88
89         # actually switch kernel contexts with ordinary exceptions disabled
90         andi            gr4,#~PSR_ET,gr5
91         movgs           gr5,psr
92
93         or.p            gr10,gr0,gr28           ; set __frame
94         or              gr11,gr0,gr29           ; set __current
95         or.p            gr12,gr0,sp
96         or              gr13,gr0,fp
97         or              gr19,gr0,gr15           ; set __current_thread_info
98
99         sti             gr7,@(gr6,#0)           ; set __kernel_frame0_ptr
100         sti             gr29,@(gr6,#4)          ; set __kernel_current_task
101
102         movgs           gr14,lr
103         bar
104
105         # jump to __switch_back or ret_from_fork as appropriate
106         # - move prev to GR8
107         movgs           gr4,psr
108         jmpl.p          @(gr18,gr0)
109         or              gr27,gr27,gr8
110
111 ###############################################################################
112 #
113 # restore incoming process's context
114 # - on entry:
115 #   - SP, FP, LR, GR15, GR28 and GR29 will have been set up appropriately
116 #   - GR8 will point to the outgoing task_struct
117 #   - GR9 will point to the incoming thread_struct
118 #
119 ###############################################################################
120 __switch_back:
121         lddi            @(gr9,#__THREAD_GR(16)),gr16
122         lddi            @(gr9,#__THREAD_GR(18)),gr18
123         lddi            @(gr9,#__THREAD_GR(20)),gr20
124         lddi            @(gr9,#__THREAD_GR(22)),gr22
125         lddi            @(gr9,#__THREAD_GR(24)),gr24
126         lddi            @(gr9,#__THREAD_GR(26)),gr26
127
128         # fall through into restore_user_regs()
129         ldi.p           @(gr9,#__THREAD_USER),gr8
130         or              gr8,gr8,gr9
131
132 ###############################################################################
133 #
134 # restore extra general regs and FP/Media regs
135 # - void *restore_user_regs(const struct user_context *target, void *retval)
136 # - on entry:
137 #   - GR8 will point to the user context to swap in
138 #   - GR9 will contain the value to be returned in GR8 (prev task on context switch)
139 #
140 ###############################################################################
141         .globl          restore_user_regs
142 restore_user_regs:
143         movsg           hsr0,gr6
144         ori             gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
145         movgs           gr6,hsr0
146         movsg           hsr0,gr6
147
148         movsg           psr,gr7
149         ori             gr7,#PSR_EF|PSR_EM,gr7
150         movgs           gr7,psr
151         movsg           psr,gr7
152         srli            gr7,#24,gr7
153         bar
154
155         lddi            @(gr8,#__FPMEDIA_MSR(0)),gr4
156
157         movgs           gr4,msr0
158         movgs           gr5,msr1
159
160         lddfi           @(gr8,#__FPMEDIA_ACC(0)),fr16
161         lddfi           @(gr8,#__FPMEDIA_ACC(2)),fr18
162         ldbfi           @(gr8,#__FPMEDIA_ACCG(0)),fr20
163         ldbfi           @(gr8,#__FPMEDIA_ACCG(1)),fr21
164         ldbfi           @(gr8,#__FPMEDIA_ACCG(2)),fr22
165         ldbfi           @(gr8,#__FPMEDIA_ACCG(3)),fr23
166
167         mwtacc          fr16,acc0
168         mwtacc          fr17,acc1
169         mwtacc          fr18,acc2
170         mwtacc          fr19,acc3
171         mwtaccg         fr20,accg0
172         mwtaccg         fr21,accg1
173         mwtaccg         fr22,accg2
174         mwtaccg         fr23,accg3
175
176         # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
177         subicc.p        gr7,#0x50,gr0,icc0
178         subicc          gr7,#0x31,gr0,icc1
179         beq             icc0,#0,__restore_acc_fr451
180         beq             icc1,#0,__restore_acc_fr555
181 __restore_acc_cont:
182
183         # some CPU's have GR32-GR63
184         setlos          #HSR0_FRHE,gr4
185         andcc           gr6,gr4,gr0,icc0
186         beq             icc0,#1,__restore_skip_gr32_gr63
187
188         lddi            @(gr8,#__INT_GR(32)),gr32
189         lddi            @(gr8,#__INT_GR(34)),gr34
190         lddi            @(gr8,#__INT_GR(36)),gr36
191         lddi            @(gr8,#__INT_GR(38)),gr38
192         lddi            @(gr8,#__INT_GR(40)),gr40
193         lddi            @(gr8,#__INT_GR(42)),gr42
194         lddi            @(gr8,#__INT_GR(44)),gr44
195         lddi            @(gr8,#__INT_GR(46)),gr46
196         lddi            @(gr8,#__INT_GR(48)),gr48
197         lddi            @(gr8,#__INT_GR(50)),gr50
198         lddi            @(gr8,#__INT_GR(52)),gr52
199         lddi            @(gr8,#__INT_GR(54)),gr54
200         lddi            @(gr8,#__INT_GR(56)),gr56
201         lddi            @(gr8,#__INT_GR(58)),gr58
202         lddi            @(gr8,#__INT_GR(60)),gr60
203         lddi            @(gr8,#__INT_GR(62)),gr62
204 __restore_skip_gr32_gr63:
205
206         # all CPU's have FR0-FR31
207         lddfi           @(gr8,#__FPMEDIA_FR( 0)),fr0
208         lddfi           @(gr8,#__FPMEDIA_FR( 2)),fr2
209         lddfi           @(gr8,#__FPMEDIA_FR( 4)),fr4
210         lddfi           @(gr8,#__FPMEDIA_FR( 6)),fr6
211         lddfi           @(gr8,#__FPMEDIA_FR( 8)),fr8
212         lddfi           @(gr8,#__FPMEDIA_FR(10)),fr10
213         lddfi           @(gr8,#__FPMEDIA_FR(12)),fr12
214         lddfi           @(gr8,#__FPMEDIA_FR(14)),fr14
215         lddfi           @(gr8,#__FPMEDIA_FR(16)),fr16
216         lddfi           @(gr8,#__FPMEDIA_FR(18)),fr18
217         lddfi           @(gr8,#__FPMEDIA_FR(20)),fr20
218         lddfi           @(gr8,#__FPMEDIA_FR(22)),fr22
219         lddfi           @(gr8,#__FPMEDIA_FR(24)),fr24
220         lddfi           @(gr8,#__FPMEDIA_FR(26)),fr26
221         lddfi           @(gr8,#__FPMEDIA_FR(28)),fr28
222         lddfi.p         @(gr8,#__FPMEDIA_FR(30)),fr30
223
224         # some CPU's have FR32-FR63
225         setlos          #HSR0_FRHE,gr4
226         andcc           gr6,gr4,gr0,icc0
227         beq             icc0,#1,__restore_skip_fr32_fr63
228
229         lddfi           @(gr8,#__FPMEDIA_FR(32)),fr32
230         lddfi           @(gr8,#__FPMEDIA_FR(34)),fr34
231         lddfi           @(gr8,#__FPMEDIA_FR(36)),fr36
232         lddfi           @(gr8,#__FPMEDIA_FR(38)),fr38
233         lddfi           @(gr8,#__FPMEDIA_FR(40)),fr40
234         lddfi           @(gr8,#__FPMEDIA_FR(42)),fr42
235         lddfi           @(gr8,#__FPMEDIA_FR(44)),fr44
236         lddfi           @(gr8,#__FPMEDIA_FR(46)),fr46
237         lddfi           @(gr8,#__FPMEDIA_FR(48)),fr48
238         lddfi           @(gr8,#__FPMEDIA_FR(50)),fr50
239         lddfi           @(gr8,#__FPMEDIA_FR(52)),fr52
240         lddfi           @(gr8,#__FPMEDIA_FR(54)),fr54
241         lddfi           @(gr8,#__FPMEDIA_FR(56)),fr56
242         lddfi           @(gr8,#__FPMEDIA_FR(58)),fr58
243         lddfi           @(gr8,#__FPMEDIA_FR(60)),fr60
244         lddfi           @(gr8,#__FPMEDIA_FR(62)),fr62
245 __restore_skip_fr32_fr63:
246
247         lddi            @(gr8,#__FPMEDIA_FNER(0)),gr4
248         movsg           fner0,gr4
249         movsg           fner1,gr5
250         or.p            gr9,gr9,gr8
251         bralr
252
253         # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
254 __restore_acc_fr451:
255         lddfi           @(gr8,#__FPMEDIA_ACC(4)),fr16
256         lddfi           @(gr8,#__FPMEDIA_ACC(6)),fr18
257         ldbfi           @(gr8,#__FPMEDIA_ACCG(4)),fr20
258         ldbfi           @(gr8,#__FPMEDIA_ACCG(5)),fr21
259         ldbfi           @(gr8,#__FPMEDIA_ACCG(6)),fr22
260         ldbfi           @(gr8,#__FPMEDIA_ACCG(7)),fr23
261
262         mwtacc          fr16,acc8
263         mwtacc          fr17,acc9
264         mwtacc          fr18,acc10
265         mwtacc          fr19,acc11
266         mwtaccg         fr20,accg8
267         mwtaccg         fr21,accg9
268         mwtaccg         fr22,accg10
269         mwtaccg         fr23,accg11
270         bra             __restore_acc_cont
271
272         # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
273 __restore_acc_fr555:
274         lddfi           @(gr8,#__FPMEDIA_ACC(4)),fr16
275         lddfi           @(gr8,#__FPMEDIA_ACC(6)),fr18
276         ldbfi           @(gr8,#__FPMEDIA_ACCG(4)),fr20
277         ldbfi           @(gr8,#__FPMEDIA_ACCG(5)),fr21
278         ldbfi           @(gr8,#__FPMEDIA_ACCG(6)),fr22
279         ldbfi           @(gr8,#__FPMEDIA_ACCG(7)),fr23
280
281         mnop.p
282         mwtacc          fr16,acc4
283         mnop.p
284         mwtacc          fr17,acc5
285         mnop.p
286         mwtacc          fr18,acc6
287         mnop.p
288         mwtacc          fr19,acc7
289         mnop.p
290         mwtaccg         fr20,accg4
291         mnop.p
292         mwtaccg         fr21,accg5
293         mnop.p
294         mwtaccg         fr22,accg6
295         mnop.p
296         mwtaccg         fr23,accg7
297
298         ldi             @(gr8,#__FPMEDIA_FSR(0)),gr4
299         movgs           gr4,fsr0
300
301         bra             __restore_acc_cont
302
303
304 ###############################################################################
305 #
306 # save extra general regs and FP/Media regs
307 # - void save_user_regs(struct user_context *target)
308 #
309 ###############################################################################
310         .globl          save_user_regs
311 save_user_regs:
312         movsg           hsr0,gr6
313         ori             gr6,#HSR0_GRHE|HSR0_FRLE|HSR0_FRHE,gr6
314         movgs           gr6,hsr0
315         movsg           hsr0,gr6
316
317         movsg           psr,gr7
318         ori             gr7,#PSR_EF|PSR_EM,gr7
319         movgs           gr7,psr
320         movsg           psr,gr7
321         srli            gr7,#24,gr7
322         bar
323
324         movsg           fner0,gr4
325         movsg           fner1,gr5
326         stdi.p          gr4,@(gr8,#__FPMEDIA_FNER(0))
327
328         # some CPU's have GR32-GR63
329         setlos          #HSR0_GRHE,gr4
330         andcc           gr6,gr4,gr0,icc0
331         beq             icc0,#1,__save_skip_gr32_gr63
332
333         stdi            gr32,@(gr8,#__INT_GR(32))
334         stdi            gr34,@(gr8,#__INT_GR(34))
335         stdi            gr36,@(gr8,#__INT_GR(36))
336         stdi            gr38,@(gr8,#__INT_GR(38))
337         stdi            gr40,@(gr8,#__INT_GR(40))
338         stdi            gr42,@(gr8,#__INT_GR(42))
339         stdi            gr44,@(gr8,#__INT_GR(44))
340         stdi            gr46,@(gr8,#__INT_GR(46))
341         stdi            gr48,@(gr8,#__INT_GR(48))
342         stdi            gr50,@(gr8,#__INT_GR(50))
343         stdi            gr52,@(gr8,#__INT_GR(52))
344         stdi            gr54,@(gr8,#__INT_GR(54))
345         stdi            gr56,@(gr8,#__INT_GR(56))
346         stdi            gr58,@(gr8,#__INT_GR(58))
347         stdi            gr60,@(gr8,#__INT_GR(60))
348         stdi            gr62,@(gr8,#__INT_GR(62))
349 __save_skip_gr32_gr63:
350
351         # all CPU's have FR0-FR31
352         stdfi           fr0 ,@(gr8,#__FPMEDIA_FR( 0))
353         stdfi           fr2 ,@(gr8,#__FPMEDIA_FR( 2))
354         stdfi           fr4 ,@(gr8,#__FPMEDIA_FR( 4))
355         stdfi           fr6 ,@(gr8,#__FPMEDIA_FR( 6))
356         stdfi           fr8 ,@(gr8,#__FPMEDIA_FR( 8))
357         stdfi           fr10,@(gr8,#__FPMEDIA_FR(10))
358         stdfi           fr12,@(gr8,#__FPMEDIA_FR(12))
359         stdfi           fr14,@(gr8,#__FPMEDIA_FR(14))
360         stdfi           fr16,@(gr8,#__FPMEDIA_FR(16))
361         stdfi           fr18,@(gr8,#__FPMEDIA_FR(18))
362         stdfi           fr20,@(gr8,#__FPMEDIA_FR(20))
363         stdfi           fr22,@(gr8,#__FPMEDIA_FR(22))
364         stdfi           fr24,@(gr8,#__FPMEDIA_FR(24))
365         stdfi           fr26,@(gr8,#__FPMEDIA_FR(26))
366         stdfi           fr28,@(gr8,#__FPMEDIA_FR(28))
367         stdfi.p         fr30,@(gr8,#__FPMEDIA_FR(30))
368
369         # some CPU's have FR32-FR63
370         setlos          #HSR0_FRHE,gr4
371         andcc           gr6,gr4,gr0,icc0
372         beq             icc0,#1,__save_skip_fr32_fr63
373
374         stdfi           fr32,@(gr8,#__FPMEDIA_FR(32))
375         stdfi           fr34,@(gr8,#__FPMEDIA_FR(34))
376         stdfi           fr36,@(gr8,#__FPMEDIA_FR(36))
377         stdfi           fr38,@(gr8,#__FPMEDIA_FR(38))
378         stdfi           fr40,@(gr8,#__FPMEDIA_FR(40))
379         stdfi           fr42,@(gr8,#__FPMEDIA_FR(42))
380         stdfi           fr44,@(gr8,#__FPMEDIA_FR(44))
381         stdfi           fr46,@(gr8,#__FPMEDIA_FR(46))
382         stdfi           fr48,@(gr8,#__FPMEDIA_FR(48))
383         stdfi           fr50,@(gr8,#__FPMEDIA_FR(50))
384         stdfi           fr52,@(gr8,#__FPMEDIA_FR(52))
385         stdfi           fr54,@(gr8,#__FPMEDIA_FR(54))
386         stdfi           fr56,@(gr8,#__FPMEDIA_FR(56))
387         stdfi           fr58,@(gr8,#__FPMEDIA_FR(58))
388         stdfi           fr60,@(gr8,#__FPMEDIA_FR(60))
389         stdfi           fr62,@(gr8,#__FPMEDIA_FR(62))
390 __save_skip_fr32_fr63:
391
392         mrdacc          acc0 ,fr4
393         mrdacc          acc1 ,fr5
394
395         stdfi.p         fr4 ,@(gr8,#__FPMEDIA_ACC(0))
396
397         mrdacc          acc2 ,fr6
398         mrdacc          acc3 ,fr7
399
400         stdfi.p         fr6 ,@(gr8,#__FPMEDIA_ACC(2))
401
402         mrdaccg         accg0,fr4
403         stbfi.p         fr4 ,@(gr8,#__FPMEDIA_ACCG(0))
404
405         mrdaccg         accg1,fr5
406         stbfi.p         fr5 ,@(gr8,#__FPMEDIA_ACCG(1))
407
408         mrdaccg         accg2,fr6
409         stbfi.p         fr6 ,@(gr8,#__FPMEDIA_ACCG(2))
410
411         mrdaccg         accg3,fr7
412         stbfi           fr7 ,@(gr8,#__FPMEDIA_ACCG(3))
413
414         movsg           msr0 ,gr4
415         movsg           msr1 ,gr5
416
417         stdi            gr4 ,@(gr8,#__FPMEDIA_MSR(0))
418
419         # some CPUs have extra ACCx and ACCGx regs and maybe FSRx regs
420         subicc.p        gr7,#0x50,gr0,icc0
421         subicc          gr7,#0x31,gr0,icc1
422         beq             icc0,#0,__save_acc_fr451
423         beq             icc1,#0,__save_acc_fr555
424 __save_acc_cont:
425
426         lddfi           @(gr8,#__FPMEDIA_FR(4)),fr4
427         lddfi.p         @(gr8,#__FPMEDIA_FR(6)),fr6
428         bralr
429
430         # the FR451 also has ACC8-11/ACCG8-11 regs (but not 4-7...)
431 __save_acc_fr451:
432         mrdacc          acc8 ,fr4
433         mrdacc          acc9 ,fr5
434
435         stdfi.p         fr4 ,@(gr8,#__FPMEDIA_ACC(4))
436
437         mrdacc          acc10,fr6
438         mrdacc          acc11,fr7
439
440         stdfi.p         fr6 ,@(gr8,#__FPMEDIA_ACC(6))
441
442         mrdaccg         accg8,fr4
443         stbfi.p         fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
444
445         mrdaccg         accg9,fr5
446         stbfi.p         fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
447
448         mrdaccg         accg10,fr6
449         stbfi.p         fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
450
451         mrdaccg         accg11,fr7
452         stbfi           fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
453         bra             __save_acc_cont
454
455         # the FR555 also has ACC4-7/ACCG4-7 regs and an FSR0 reg
456 __save_acc_fr555:
457         mnop.p
458         mrdacc          acc4 ,fr4
459         mnop.p
460         mrdacc          acc5 ,fr5
461
462         stdfi           fr4 ,@(gr8,#__FPMEDIA_ACC(4))
463
464         mnop.p
465         mrdacc          acc6 ,fr6
466         mnop.p
467         mrdacc          acc7 ,fr7
468
469         stdfi           fr6 ,@(gr8,#__FPMEDIA_ACC(6))
470
471         mnop.p
472         mrdaccg         accg4,fr4
473         stbfi           fr4 ,@(gr8,#__FPMEDIA_ACCG(4))
474
475         mnop.p
476         mrdaccg         accg5,fr5
477         stbfi           fr5 ,@(gr8,#__FPMEDIA_ACCG(5))
478
479         mnop.p
480         mrdaccg         accg6,fr6
481         stbfi           fr6 ,@(gr8,#__FPMEDIA_ACCG(6))
482
483         mnop.p
484         mrdaccg         accg7,fr7
485         stbfi           fr7 ,@(gr8,#__FPMEDIA_ACCG(7))
486
487         movsg           fsr0 ,gr4
488         sti             gr4 ,@(gr8,#__FPMEDIA_FSR(0))
489         bra             __save_acc_cont