xref: /openbmc/linux/arch/m68k/kernel/entry.S (revision b181f7029bd71238ac2754ce7052dffd69432085)
114be4252SGreg Ungerer/* -*- mode: asm -*-
214be4252SGreg Ungerer *
314be4252SGreg Ungerer *  linux/arch/m68k/kernel/entry.S
414be4252SGreg Ungerer *
514be4252SGreg Ungerer *  Copyright (C) 1991, 1992  Linus Torvalds
614be4252SGreg Ungerer *
714be4252SGreg Ungerer * This file is subject to the terms and conditions of the GNU General Public
814be4252SGreg Ungerer * License.  See the file README.legal in the main directory of this archive
914be4252SGreg Ungerer * for more details.
1014be4252SGreg Ungerer *
1114be4252SGreg Ungerer * Linux/m68k support by Hamish Macdonald
1214be4252SGreg Ungerer *
1314be4252SGreg Ungerer * 68060 fixes by Jesper Skov
1414be4252SGreg Ungerer *
1514be4252SGreg Ungerer */
1614be4252SGreg Ungerer
1714be4252SGreg Ungerer/*
1814be4252SGreg Ungerer * entry.S  contains the system-call and fault low-level handling routines.
1914be4252SGreg Ungerer * This also contains the timer-interrupt handler, as well as all interrupts
2014be4252SGreg Ungerer * and faults that can result in a task-switch.
2114be4252SGreg Ungerer *
2214be4252SGreg Ungerer * NOTE: This code handles signal-recognition, which happens every time
2314be4252SGreg Ungerer * after a timer-interrupt and after each system call.
2414be4252SGreg Ungerer *
2514be4252SGreg Ungerer */
2614be4252SGreg Ungerer
2714be4252SGreg Ungerer/*
2814be4252SGreg Ungerer * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
2914be4252SGreg Ungerer *               all pointers that used to be 'current' are now entry
3014be4252SGreg Ungerer *               number 0 in the 'current_set' list.
3114be4252SGreg Ungerer *
3214be4252SGreg Ungerer *  6/05/00 RZ:	 addedd writeback completion after return from sighandler
3314be4252SGreg Ungerer *		 for 68040
3414be4252SGreg Ungerer */
3514be4252SGreg Ungerer
3614be4252SGreg Ungerer#include <linux/linkage.h>
3714be4252SGreg Ungerer#include <asm/errno.h>
3814be4252SGreg Ungerer#include <asm/setup.h>
3914be4252SGreg Ungerer#include <asm/traps.h>
4014be4252SGreg Ungerer#include <asm/unistd.h>
4114be4252SGreg Ungerer#include <asm/asm-offsets.h>
4214be4252SGreg Ungerer#include <asm/entry.h>
4314be4252SGreg Ungerer
4414be4252SGreg Ungerer.globl system_call, buserr, trap, resume
4514be4252SGreg Ungerer.globl sys_call_table
4620ecc91cSAl Viro.globl __sys_fork, __sys_clone, __sys_vfork
4709f90f66SThomas Gleixner.globl bad_interrupt
4814be4252SGreg Ungerer.globl auto_irqhandler_fixup
4914be4252SGreg Ungerer.globl user_irqvec_fixup
5014be4252SGreg Ungerer
5114be4252SGreg Ungerer.text
5220ecc91cSAl ViroENTRY(__sys_fork)
5314be4252SGreg Ungerer	SAVE_SWITCH_STACK
5420ecc91cSAl Viro	jbsr	sys_fork
5520ecc91cSAl Viro	lea     %sp@(24),%sp
5614be4252SGreg Ungerer	rts
5714be4252SGreg Ungerer
5820ecc91cSAl ViroENTRY(__sys_clone)
5914be4252SGreg Ungerer	SAVE_SWITCH_STACK
6014be4252SGreg Ungerer	pea	%sp@(SWITCH_STACK_SIZE)
6114be4252SGreg Ungerer	jbsr	m68k_clone
6220ecc91cSAl Viro	lea     %sp@(28),%sp
6314be4252SGreg Ungerer	rts
6414be4252SGreg Ungerer
6520ecc91cSAl ViroENTRY(__sys_vfork)
6614be4252SGreg Ungerer	SAVE_SWITCH_STACK
6720ecc91cSAl Viro	jbsr	sys_vfork
6820ecc91cSAl Viro	lea     %sp@(24),%sp
6914be4252SGreg Ungerer	rts
7014be4252SGreg Ungerer
71e8bb2a2aSKars de JongENTRY(__sys_clone3)
72e8bb2a2aSKars de Jong	SAVE_SWITCH_STACK
73e8bb2a2aSKars de Jong	pea	%sp@(SWITCH_STACK_SIZE)
74e8bb2a2aSKars de Jong	jbsr	m68k_clone3
75e8bb2a2aSKars de Jong	lea	%sp@(28),%sp
76e8bb2a2aSKars de Jong	rts
77e8bb2a2aSKars de Jong
7814be4252SGreg UngererENTRY(sys_sigreturn)
7914be4252SGreg Ungerer	SAVE_SWITCH_STACK
800d20abdeSAl Viro	movel	%sp,%a1			  	| switch_stack pointer
810d20abdeSAl Viro	lea	%sp@(SWITCH_STACK_SIZE),%a0	| pt_regs pointer
820d20abdeSAl Viro	lea     %sp@(-84),%sp			| leave a gap
830d20abdeSAl Viro	movel	%a1,%sp@-
840d20abdeSAl Viro	movel	%a0,%sp@-
8514be4252SGreg Ungerer	jbsr	do_sigreturn
860d20abdeSAl Viro	jra	1f				| shared with rt_sigreturn()
8714be4252SGreg Ungerer
8814be4252SGreg UngererENTRY(sys_rt_sigreturn)
8914be4252SGreg Ungerer	SAVE_SWITCH_STACK
900d20abdeSAl Viro	movel	%sp,%a1			  	| switch_stack pointer
910d20abdeSAl Viro	lea	%sp@(SWITCH_STACK_SIZE),%a0	| pt_regs pointer
920d20abdeSAl Viro	lea     %sp@(-84),%sp			| leave a gap
930d20abdeSAl Viro	movel	%a1,%sp@-
940d20abdeSAl Viro	movel	%a0,%sp@-
950d20abdeSAl Viro	| stack contents:
960d20abdeSAl Viro	|   [original pt_regs address] [original switch_stack address]
970d20abdeSAl Viro	|   [gap] [switch_stack] [pt_regs] [exception frame]
9814be4252SGreg Ungerer	jbsr	do_rt_sigreturn
990d20abdeSAl Viro
1000d20abdeSAl Viro1:
1010d20abdeSAl Viro	| stack contents now:
1020d20abdeSAl Viro	|   [original pt_regs address] [original switch_stack address]
1030d20abdeSAl Viro	|   [unused part of the gap] [moved switch_stack] [moved pt_regs]
1040d20abdeSAl Viro	|   [replacement exception frame]
1050d20abdeSAl Viro	| return value of do_{rt_,}sigreturn() points to moved switch_stack.
1060d20abdeSAl Viro
1070d20abdeSAl Viro	movel	%d0,%sp				| discard the leftover junk
10814be4252SGreg Ungerer	RESTORE_SWITCH_STACK
1090d20abdeSAl Viro	| stack contents now is just [syscall return address] [pt_regs] [frame]
1100d20abdeSAl Viro	| return pt_regs.d0
1110d20abdeSAl Viro	movel	%sp@(PT_OFF_D0+4),%d0
11214be4252SGreg Ungerer	rts
11314be4252SGreg Ungerer
11414be4252SGreg UngererENTRY(buserr)
11514be4252SGreg Ungerer	SAVE_ALL_INT
11614be4252SGreg Ungerer	GET_CURRENT(%d0)
11714be4252SGreg Ungerer	movel	%sp,%sp@-		| stack frame pointer argument
11814be4252SGreg Ungerer	jbsr	buserr_c
11914be4252SGreg Ungerer	addql	#4,%sp
12014be4252SGreg Ungerer	jra	ret_from_exception
12114be4252SGreg Ungerer
12214be4252SGreg UngererENTRY(trap)
12314be4252SGreg Ungerer	SAVE_ALL_INT
12414be4252SGreg Ungerer	GET_CURRENT(%d0)
12514be4252SGreg Ungerer	movel	%sp,%sp@-		| stack frame pointer argument
12614be4252SGreg Ungerer	jbsr	trap_c
12714be4252SGreg Ungerer	addql	#4,%sp
12814be4252SGreg Ungerer	jra	ret_from_exception
12914be4252SGreg Ungerer
13014be4252SGreg Ungerer	| After a fork we jump here directly from resume,
13114be4252SGreg Ungerer	| so that %d1 contains the previous task
13214be4252SGreg Ungerer	| schedule_tail now used regardless of CONFIG_SMP
13314be4252SGreg UngererENTRY(ret_from_fork)
13414be4252SGreg Ungerer	movel	%d1,%sp@-
13514be4252SGreg Ungerer	jsr	schedule_tail
13614be4252SGreg Ungerer	addql	#4,%sp
13714be4252SGreg Ungerer	jra	ret_from_exception
13814be4252SGreg Ungerer
139533e6903SAl ViroENTRY(ret_from_kernel_thread)
140533e6903SAl Viro	| a3 contains the kernel thread payload, d7 - its argument
141533e6903SAl Viro	movel	%d1,%sp@-
142533e6903SAl Viro	jsr	schedule_tail
143533e6903SAl Viro	movel	%d7,(%sp)
144533e6903SAl Viro	jsr	%a3@
145533e6903SAl Viro	addql	#4,%sp
146d878d6daSAl Viro	jra	ret_from_exception
147d878d6daSAl Viro
14814be4252SGreg Ungerer#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
14914be4252SGreg Ungerer
15014be4252SGreg Ungerer#ifdef TRAP_DBG_INTERRUPT
15114be4252SGreg Ungerer
15214be4252SGreg Ungerer.globl dbginterrupt
15314be4252SGreg UngererENTRY(dbginterrupt)
15414be4252SGreg Ungerer	SAVE_ALL_INT
15514be4252SGreg Ungerer	GET_CURRENT(%d0)
15614be4252SGreg Ungerer	movel	%sp,%sp@- 		/* stack frame pointer argument */
15714be4252SGreg Ungerer	jsr	dbginterrupt_c
15814be4252SGreg Ungerer	addql	#4,%sp
15914be4252SGreg Ungerer	jra	ret_from_exception
1601da177e4SLinus Torvalds#endif
16114be4252SGreg Ungerer
16214be4252SGreg UngererENTRY(reschedule)
16314be4252SGreg Ungerer	/* save top of frame */
16414be4252SGreg Ungerer	pea	%sp@
16514be4252SGreg Ungerer	jbsr	set_esp0
16614be4252SGreg Ungerer	addql	#4,%sp
16714be4252SGreg Ungerer	pea	ret_from_exception
16814be4252SGreg Ungerer	jmp	schedule
16914be4252SGreg Ungerer
17014be4252SGreg UngererENTRY(ret_from_user_signal)
17114be4252SGreg Ungerer	moveq #__NR_sigreturn,%d0
17214be4252SGreg Ungerer	trap #0
17314be4252SGreg Ungerer
17414be4252SGreg UngererENTRY(ret_from_user_rt_signal)
17514be4252SGreg Ungerer	movel #__NR_rt_sigreturn,%d0
17614be4252SGreg Ungerer	trap #0
17714be4252SGreg Ungerer
17814be4252SGreg Ungerer#else
17914be4252SGreg Ungerer
18014be4252SGreg Ungererdo_trace_entry:
18114be4252SGreg Ungerer	movel	#-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
18214be4252SGreg Ungerer	subql	#4,%sp
18314be4252SGreg Ungerer	SAVE_SWITCH_STACK
184c862fe70SMichael Schmitz	jbsr	syscall_trace_enter
18514be4252SGreg Ungerer	RESTORE_SWITCH_STACK
18614be4252SGreg Ungerer	addql	#4,%sp
1872ca8a1deSMichael Schmitz	addql	#1,%d0			| optimization for cmpil #-1,%d0
1882ca8a1deSMichael Schmitz	jeq	ret_from_syscall
18914be4252SGreg Ungerer	movel	%sp@(PT_OFF_ORIG_D0),%d0
19014be4252SGreg Ungerer	cmpl	#NR_syscalls,%d0
19114be4252SGreg Ungerer	jcs	syscall
1922ca8a1deSMichael Schmitz	jra	ret_from_syscall
19314be4252SGreg Ungererbadsys:
19414be4252SGreg Ungerer	movel	#-ENOSYS,%sp@(PT_OFF_D0)
19514be4252SGreg Ungerer	jra	ret_from_syscall
19614be4252SGreg Ungerer
19714be4252SGreg Ungererdo_trace_exit:
19814be4252SGreg Ungerer	subql	#4,%sp
19914be4252SGreg Ungerer	SAVE_SWITCH_STACK
200c862fe70SMichael Schmitz	jbsr	syscall_trace_leave
20114be4252SGreg Ungerer	RESTORE_SWITCH_STACK
20214be4252SGreg Ungerer	addql	#4,%sp
20314be4252SGreg Ungerer	jra	.Lret_from_exception
20414be4252SGreg Ungerer
20514be4252SGreg UngererENTRY(system_call)
20614be4252SGreg Ungerer	SAVE_ALL_SYS
20714be4252SGreg Ungerer
20814be4252SGreg Ungerer	GET_CURRENT(%d1)
20914be4252SGreg Ungerer	movel	%d1,%a1
21014be4252SGreg Ungerer
21114be4252SGreg Ungerer	| save top of frame
21214be4252SGreg Ungerer	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
21314be4252SGreg Ungerer
21414be4252SGreg Ungerer	| syscall trace?
21514be4252SGreg Ungerer	tstb	%a1@(TINFO_FLAGS+2)
21614be4252SGreg Ungerer	jmi	do_trace_entry
2176baaade1SMichael Schmitz	| seccomp filter active?
2186baaade1SMichael Schmitz	btst	#5,%a1@(TINFO_FLAGS+2)
2196baaade1SMichael Schmitz	bnes	do_trace_entry
22014be4252SGreg Ungerer	cmpl	#NR_syscalls,%d0
22114be4252SGreg Ungerer	jcc	badsys
22214be4252SGreg Ungerersyscall:
22314be4252SGreg Ungerer	jbsr	@(sys_call_table,%d0:l:4)@(0)
22414be4252SGreg Ungerer	movel	%d0,%sp@(PT_OFF_D0)	| save the return value
22514be4252SGreg Ungererret_from_syscall:
22614be4252SGreg Ungerer	|oriw	#0x0700,%sr
22714be4252SGreg Ungerer	movel	%curptr@(TASK_STACK),%a1
22814be4252SGreg Ungerer	movew	%a1@(TINFO_FLAGS+2),%d0
22914be4252SGreg Ungerer	jne	syscall_exit_work
23014be4252SGreg Ungerer1:	RESTORE_ALL
23114be4252SGreg Ungerer
23214be4252SGreg Ungerersyscall_exit_work:
23314be4252SGreg Ungerer	btst	#5,%sp@(PT_OFF_SR)	| check if returning to kernel
23414be4252SGreg Ungerer	bnes	1b			| if so, skip resched, signals
23514be4252SGreg Ungerer	lslw	#1,%d0
23614be4252SGreg Ungerer	jcs	do_trace_exit
23714be4252SGreg Ungerer	jmi	do_delayed_trace
23814be4252SGreg Ungerer	lslw	#8,%d0
23914be4252SGreg Ungerer	jne	do_signal_return
24014be4252SGreg Ungerer	pea	resume_userspace
24114be4252SGreg Ungerer	jra	schedule
24214be4252SGreg Ungerer
24314be4252SGreg Ungerer
24414be4252SGreg UngererENTRY(ret_from_exception)
24514be4252SGreg Ungerer.Lret_from_exception:
24614be4252SGreg Ungerer	btst	#5,%sp@(PT_OFF_SR)	| check if returning to kernel
24714be4252SGreg Ungerer	bnes	1f			| if so, skip resched, signals
24814be4252SGreg Ungerer	| only allow interrupts when we are really the last one on the
24914be4252SGreg Ungerer	| kernel stack, otherwise stack overflow can occur during
25014be4252SGreg Ungerer	| heavy interrupt load
25114be4252SGreg Ungerer	andw	#ALLOWINT,%sr
25214be4252SGreg Ungerer
25314be4252SGreg Ungererresume_userspace:
25414be4252SGreg Ungerer	movel	%curptr@(TASK_STACK),%a1
25514be4252SGreg Ungerer	moveb	%a1@(TINFO_FLAGS+3),%d0
25614be4252SGreg Ungerer	jne	exit_work
25714be4252SGreg Ungerer1:	RESTORE_ALL
25814be4252SGreg Ungerer
25914be4252SGreg Ungererexit_work:
26014be4252SGreg Ungerer	| save top of frame
26114be4252SGreg Ungerer	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
26214be4252SGreg Ungerer	lslb	#1,%d0
26314be4252SGreg Ungerer	jne	do_signal_return
26414be4252SGreg Ungerer	pea	resume_userspace
26514be4252SGreg Ungerer	jra	schedule
26614be4252SGreg Ungerer
26714be4252SGreg Ungerer
26814be4252SGreg Ungererdo_signal_return:
26914be4252SGreg Ungerer	|andw	#ALLOWINT,%sr
27014be4252SGreg Ungerer	subql	#4,%sp			| dummy return address
27114be4252SGreg Ungerer	SAVE_SWITCH_STACK
27214be4252SGreg Ungerer	pea	%sp@(SWITCH_STACK_SIZE)
27314be4252SGreg Ungerer	bsrl	do_notify_resume
27414be4252SGreg Ungerer	addql	#4,%sp
27514be4252SGreg Ungerer	RESTORE_SWITCH_STACK
27614be4252SGreg Ungerer	addql	#4,%sp
27714be4252SGreg Ungerer	jbra	resume_userspace
27814be4252SGreg Ungerer
27914be4252SGreg Ungererdo_delayed_trace:
28014be4252SGreg Ungerer	bclr	#7,%sp@(PT_OFF_SR)	| clear trace bit in SR
28114be4252SGreg Ungerer	pea	1			| send SIGTRAP
28214be4252SGreg Ungerer	movel	%curptr,%sp@-
28314be4252SGreg Ungerer	pea	LSIGTRAP
28414be4252SGreg Ungerer	jbsr	send_sig
28514be4252SGreg Ungerer	addql	#8,%sp
28614be4252SGreg Ungerer	addql	#4,%sp
28714be4252SGreg Ungerer	jbra	resume_userspace
28814be4252SGreg Ungerer
28914be4252SGreg Ungerer
29014be4252SGreg Ungerer/* This is the main interrupt handler for autovector interrupts */
29114be4252SGreg Ungerer
29214be4252SGreg UngererENTRY(auto_inthandler)
29314be4252SGreg Ungerer	SAVE_ALL_INT
29414be4252SGreg Ungerer	GET_CURRENT(%d0)
29514be4252SGreg Ungerer					|  put exception # in d0
29614be4252SGreg Ungerer	bfextu	%sp@(PT_OFF_FORMATVEC){#4,#10},%d0
29714be4252SGreg Ungerer	subw	#VEC_SPUR,%d0
29814be4252SGreg Ungerer
29914be4252SGreg Ungerer	movel	%sp,%sp@-
30014be4252SGreg Ungerer	movel	%d0,%sp@-		|  put vector # on stack
30114be4252SGreg Ungererauto_irqhandler_fixup = . + 2
30214be4252SGreg Ungerer	jsr	do_IRQ			|  process the IRQ
30314be4252SGreg Ungerer	addql	#8,%sp			|  pop parameters off stack
30409f90f66SThomas Gleixner	jra	ret_from_exception
30514be4252SGreg Ungerer
30614be4252SGreg Ungerer/* Handler for user defined interrupt vectors */
30714be4252SGreg Ungerer
30814be4252SGreg UngererENTRY(user_inthandler)
30914be4252SGreg Ungerer	SAVE_ALL_INT
31014be4252SGreg Ungerer	GET_CURRENT(%d0)
31114be4252SGreg Ungerer					|  put exception # in d0
31214be4252SGreg Ungerer	bfextu	%sp@(PT_OFF_FORMATVEC){#4,#10},%d0
31314be4252SGreg Ungereruser_irqvec_fixup = . + 2
31414be4252SGreg Ungerer	subw	#VEC_USER,%d0
31514be4252SGreg Ungerer
31614be4252SGreg Ungerer	movel	%sp,%sp@-
31714be4252SGreg Ungerer	movel	%d0,%sp@-		|  put vector # on stack
31814be4252SGreg Ungerer	jsr	do_IRQ			|  process the IRQ
31914be4252SGreg Ungerer	addql	#8,%sp			|  pop parameters off stack
32009f90f66SThomas Gleixner	jra	ret_from_exception
32114be4252SGreg Ungerer
32214be4252SGreg Ungerer/* Handler for uninitialized and spurious interrupts */
32314be4252SGreg Ungerer
32414be4252SGreg UngererENTRY(bad_inthandler)
32514be4252SGreg Ungerer	SAVE_ALL_INT
32614be4252SGreg Ungerer	GET_CURRENT(%d0)
32714be4252SGreg Ungerer
32814be4252SGreg Ungerer	movel	%sp,%sp@-
32914be4252SGreg Ungerer	jsr	handle_badint
33014be4252SGreg Ungerer	addql	#4,%sp
33109f90f66SThomas Gleixner	jra	ret_from_exception
33214be4252SGreg Ungerer
33314be4252SGreg Ungererresume:
33414be4252SGreg Ungerer	/*
33514be4252SGreg Ungerer	 * Beware - when entering resume, prev (the current task) is
33614be4252SGreg Ungerer	 * in a0, next (the new task) is in a1,so don't change these
33714be4252SGreg Ungerer	 * registers until their contents are no longer needed.
33814be4252SGreg Ungerer	 */
33914be4252SGreg Ungerer
34014be4252SGreg Ungerer	/* save sr */
34114be4252SGreg Ungerer	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)
34214be4252SGreg Ungerer
34314be4252SGreg Ungerer	/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
34414be4252SGreg Ungerer	movec	%sfc,%d0
3459fde0348SChristoph Hellwig	movew	%d0,%a0@(TASK_THREAD+THREAD_FC)
34614be4252SGreg Ungerer
34714be4252SGreg Ungerer	/* save usp */
34814be4252SGreg Ungerer	/* it is better to use a movel here instead of a movew 8*) */
34914be4252SGreg Ungerer	movec	%usp,%d0
35014be4252SGreg Ungerer	movel	%d0,%a0@(TASK_THREAD+THREAD_USP)
35114be4252SGreg Ungerer
35214be4252SGreg Ungerer	/* save non-scratch registers on stack */
35314be4252SGreg Ungerer	SAVE_SWITCH_STACK
35414be4252SGreg Ungerer
35514be4252SGreg Ungerer	/* save current kernel stack pointer */
35614be4252SGreg Ungerer	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP)
35714be4252SGreg Ungerer
35814be4252SGreg Ungerer	/* save floating point context */
35914be4252SGreg Ungerer#ifndef CONFIG_M68KFPU_EMU_ONLY
36014be4252SGreg Ungerer#ifdef CONFIG_M68KFPU_EMU
36114be4252SGreg Ungerer	tstl	m68k_fputype
36214be4252SGreg Ungerer	jeq	3f
36314be4252SGreg Ungerer#endif
36414be4252SGreg Ungerer	fsave	%a0@(TASK_THREAD+THREAD_FPSTATE)
36514be4252SGreg Ungerer
36614be4252SGreg Ungerer#if defined(CONFIG_M68060)
36714be4252SGreg Ungerer#if !defined(CPU_M68060_ONLY)
36814be4252SGreg Ungerer	btst	#3,m68k_cputype+3
36914be4252SGreg Ungerer	beqs	1f
37014be4252SGreg Ungerer#endif
37114be4252SGreg Ungerer	/* The 060 FPU keeps status in bits 15-8 of the first longword */
37214be4252SGreg Ungerer	tstb	%a0@(TASK_THREAD+THREAD_FPSTATE+2)
37314be4252SGreg Ungerer	jeq	3f
37414be4252SGreg Ungerer#if !defined(CPU_M68060_ONLY)
37514be4252SGreg Ungerer	jra	2f
37614be4252SGreg Ungerer#endif
37714be4252SGreg Ungerer#endif /* CONFIG_M68060 */
37814be4252SGreg Ungerer#if !defined(CPU_M68060_ONLY)
37914be4252SGreg Ungerer1:	tstb	%a0@(TASK_THREAD+THREAD_FPSTATE)
38014be4252SGreg Ungerer	jeq	3f
38114be4252SGreg Ungerer#endif
38214be4252SGreg Ungerer2:	fmovemx	%fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
38314be4252SGreg Ungerer	fmoveml	%fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
38414be4252SGreg Ungerer3:
38514be4252SGreg Ungerer#endif	/* CONFIG_M68KFPU_EMU_ONLY */
38614be4252SGreg Ungerer	/* Return previous task in %d1 */
38714be4252SGreg Ungerer	movel	%curptr,%d1
38814be4252SGreg Ungerer
38914be4252SGreg Ungerer	/* switch to new task (a1 contains new task) */
39014be4252SGreg Ungerer	movel	%a1,%curptr
39114be4252SGreg Ungerer
39214be4252SGreg Ungerer	/* restore floating point context */
39314be4252SGreg Ungerer#ifndef CONFIG_M68KFPU_EMU_ONLY
39414be4252SGreg Ungerer#ifdef CONFIG_M68KFPU_EMU
39514be4252SGreg Ungerer	tstl	m68k_fputype
39614be4252SGreg Ungerer	jeq	4f
39714be4252SGreg Ungerer#endif
39814be4252SGreg Ungerer#if defined(CONFIG_M68060)
39914be4252SGreg Ungerer#if !defined(CPU_M68060_ONLY)
40014be4252SGreg Ungerer	btst	#3,m68k_cputype+3
40114be4252SGreg Ungerer	beqs	1f
40214be4252SGreg Ungerer#endif
40314be4252SGreg Ungerer	/* The 060 FPU keeps status in bits 15-8 of the first longword */
40414be4252SGreg Ungerer	tstb	%a1@(TASK_THREAD+THREAD_FPSTATE+2)
40514be4252SGreg Ungerer	jeq	3f
40614be4252SGreg Ungerer#if !defined(CPU_M68060_ONLY)
40714be4252SGreg Ungerer	jra	2f
40814be4252SGreg Ungerer#endif
40914be4252SGreg Ungerer#endif /* CONFIG_M68060 */
41014be4252SGreg Ungerer#if !defined(CPU_M68060_ONLY)
41114be4252SGreg Ungerer1:	tstb	%a1@(TASK_THREAD+THREAD_FPSTATE)
41214be4252SGreg Ungerer	jeq	3f
41314be4252SGreg Ungerer#endif
41414be4252SGreg Ungerer2:	fmovemx	%a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
41514be4252SGreg Ungerer	fmoveml	%a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
41614be4252SGreg Ungerer3:	frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
41714be4252SGreg Ungerer4:
41814be4252SGreg Ungerer#endif	/* CONFIG_M68KFPU_EMU_ONLY */
41914be4252SGreg Ungerer
42014be4252SGreg Ungerer	/* restore the kernel stack pointer */
42114be4252SGreg Ungerer	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp
42214be4252SGreg Ungerer
42314be4252SGreg Ungerer	/* restore non-scratch registers */
42414be4252SGreg Ungerer	RESTORE_SWITCH_STACK
42514be4252SGreg Ungerer
42614be4252SGreg Ungerer	/* restore user stack pointer */
42714be4252SGreg Ungerer	movel	%a1@(TASK_THREAD+THREAD_USP),%a0
42814be4252SGreg Ungerer	movel	%a0,%usp
42914be4252SGreg Ungerer
43014be4252SGreg Ungerer	/* restore fs (sfc,%dfc) */
4319fde0348SChristoph Hellwig	movew	%a1@(TASK_THREAD+THREAD_FC),%a0
43214be4252SGreg Ungerer	movec	%a0,%sfc
43314be4252SGreg Ungerer	movec	%a0,%dfc
43414be4252SGreg Ungerer
43514be4252SGreg Ungerer	/* restore status register */
436*f3baf0f4SMichael Schmitz	movew	%a1@(TASK_THREAD+THREAD_SR),%d0
437*f3baf0f4SMichael Schmitz	oriw	#0x0700,%d0
438*f3baf0f4SMichael Schmitz	movew	%d0,%sr
43914be4252SGreg Ungerer
44014be4252SGreg Ungerer	rts
44114be4252SGreg Ungerer
44214be4252SGreg Ungerer#endif /* CONFIG_MMU && !CONFIG_COLDFIRE */
443