/*
 * This file contains the code necessary to switch
 * tasks on an m680x0 linux machine.
 * The following LTSS_ constants must be changed if the m68k_struct in
 * include/linux/sched.h is changed.
 * The LBI_CPU constant must be changed if the boot_info structure is 
 * changed. 
 */

#include <linux/linkage.h>

LFLUSH_I_AND_D = 0x00000808
LBI_CPU = 4
LTSS_SR = 48
LTSS_REGS = 0
LTSS_FS = 50
LTSS_CRP = 60
LTSS_FPREGS = 68
LTSS_FPCNTL = 164
LTSS_FPSTATE = 176

.text

ENTRY(resume)
	/* current tasks task_struct */
	movel	SYMBOL_NAME(current),%a0

	/* offset of tss struct (processor state) from beginning
	   of task struct */
	movel	%sp@(8),%a1
	addl	%a1,%a0

	/* save sr */
	movew	%sr,%a0@(LTSS_SR)

	/* disable interrupts */
	oriw	#0x0700,%sr

	/* save fs (sfc,dfc) (may be pointing to kernel memory) */
	movec	%sfc,%d0
	movew	%d0,%a0@(LTSS_FS)

	/* save non-scratch registers */
	moveml	%d2-%d7/%a2-%a7,%a0@(LTSS_REGS)

	/* save floating point state */
	fsave	%a0@(LTSS_FPSTATE)
	tstb	%a0@(LTSS_FPSTATE)
	beqs	1f	    /* NULL state, no need to save regs */
	fmovemx %fp0-%fp7,%a0@(LTSS_FPREGS)
	fmovem	%fpiar/%fpcr/%fpsr,%a0@(LTSS_FPCNTL)
1:

	/* switch current task */
	movel	%sp@(4),%a0
	movel	%a0,SYMBOL_NAME(current)
	/* get pointer to tss struct */
	addl	%a1,%a0

	/* 68040 or 68060 ? */
	btst	#2,SYMBOL_NAME(boot_info)+LBI_CPU+3
	bnes	1f
	btst	#3,SYMBOL_NAME(boot_info)+LBI_CPU+3
	bnes	1f

	/*
	 * switch address space
	 */

	/* flush MC68030/MC68020 caches (they are virtually addressed) */
	movec	%cacr,%d0
	oril	#LFLUSH_I_AND_D,%d0
	movec	%d0,%cacr

	/* switch the root pointer */
	pmove	%a0@(LTSS_CRP),%crp

	/* flush address translation cache (probably not needed */
	pflusha

	bras	2f	/* skip m68040 stuff */

1:
	/*
	 * switch address space
	 */

	/* flush address translation cache (user entries) */
	.word	0xf510			/* pflushan */

	/* switch the root pointer */
	movel	%a0@(LTSS_CRP+4),%d0
	.long	0x4e7b0806		/* movec d0,urp */

	/* is it a '060 ? */
	btst	#3,SYMBOL_NAME(boot_info)+LBI_CPU+3
	beqs	2f
	/* clear user entries in the branch cache */
	movec	%cacr,%d0
	orl	#0x00200000,%d0
	movec	%d0,%cacr

2:
	/* restore floating point unit state */
	tstb	%a0@(LTSS_FPSTATE)
	beqs	1f	    /* NULL state; no need to load regs */
	fmovemx %a0@(LTSS_FPREGS),%fp0-%fp7
	fmovem	%a0@(LTSS_FPCNTL),%fpiar/%fpcr/%fpsr
1:
	frestore %a0@(LTSS_FPSTATE)

	/* restore non-scratch registers */
	moveml	%a0@(LTSS_REGS),%d2-%d7/%a2-%a7

	/* restore fs (sfc,dfc) */
	movew	%a0@(LTSS_FS),%a1
	movec	%a1,%sfc
	movec	%a1,%dfc

	/* restore status register */
	movew	%a0@(LTSS_SR),%sr

	rts

ENTRY(__ashrdi3)
	linkw %fp,#0
	moveml %d2-%d7,%sp@-
	movel %fp@(8),%d4
	movel %fp@(12),%d5
	movel %fp@(16),%d6
	bnes 1f
	movel %d4,%d0
	movel %d5,%d1
	bras 2f
1:	moveq #32,%d0
	subl %d6,%d0
	tstl %d0
	bgts 3f
	movel %d4,%d2
	moveq #31,%d7
	asrl %d7,%d2
	negl %d0
	movel %d4,%d3
	asrl %d0,%d3
	bras 4f
3:	movel %d4,%d1
	asll %d0,%d1
	movel %d4,%d2
	asrl %d6,%d2
	movel %d5,%d0
	lsrl %d6,%d0
	movel %d0,%d3
	orl %d1,%d3
4:	movel %d2,%d0
	movel %d3,%d1
2:	moveml %fp@(-24),%d2-%d7
	unlk %fp
	rts


#if 0
ENTRY(__cmpdi2)
	linkw %fp,#0
	movel %d2,%sp@-
	movel %fp@(8),%d1
	movel %fp@(12),%d2
	moveal %fp@(16),%a0
	moveal %fp@(20),%a1
	cmpal %d1,%a0
	bgts 1f
	bges 2f
	moveq #2,%d0
	bras 3f
2:	cmpal %d2,%a1
	blss 4f
1:	clrl %d0
	bras 3f
4:	moveq #2,%d0
	cmpal %d2,%a1
	bcss 3f
	moveq #1,%d0
3:	movel %fp@(-4),%d2
	unlk %fp
	rts

ENTRY(__divdi3)
	linkw %fp,#-8
	moveml %d2-%d7/%a2-%a4,%sp@-
	subal %a4,%a4
	movel %fp@(8),%d4
	movel %fp@(12),%d5
	movel %fp@(16),%d2
	movel %fp@(20),%d3
	tstl %d4
	jge 2f /* ___divdi3+0x38 */
	moveaw #-1,%a4
	movel %d5,%d0
	negl %d0
	moveal %d0,%a1
	movel %d4,%d1
	negl %d1
	tstl %d0
	jeq 1f /* ___divdi3+0x32 */
	subl #1,%d1
1:	moveal %d1,%a0
	movel %a0,%d4
	movel %a1,%d5
2:	tstl %d2
	jge 3f /* ___divdi3+0x60 */
	movel %a4,%d6
	notl %d6
	moveal %d6,%a4
	movel %d3,%d0
	negl %d0
	movel %d0,%fp@(-4)
	movel %d2,%d1
	negl %d1
	tstl %d0
	jeq 4f /* ___divdi3+0x54 */
	subl #1,%d1
4:	movel %d1,%fp@(-8)
	movel %fp@(-8),%d2
	movel %fp@(-4),%d3
3:	clrl %sp@-
	movel %d3,%sp@-
	movel %d2,%sp@-
	movel %d5,%sp@-
	movel %d4,%sp@-
	jbsr SYMBOL_NAME(__divdi3)
	movel %d1,%d2
	movel %d0,%d1
	tstl %a4
	jeq 6f /* ___divdi3+0x8c */
	movel %d2,%d0
	negl %d0
	moveal %d0,%a3
	negl %d1
	tstl %d0
	jeq 5f /* ___divdi3+0x86 */
	subl #1,%d1
5:	moveal %d1,%a2
	movel %a2,%d1
	movel %a3,%d2
6:	movel %d1,%d0
	movel %d2,%d1
	moveml %fp@(-44),%d2-%d7/%a2-%a4
	unlk %fp
	rts
#endif
