#include <linux/autoconf.h>

#include "assyms.h"

LBITS_040 = LPAGE_PRESENT|LPAGE_CACHE040

.text
	.even
.globl _mach_save_ctx
_mach_save_ctx:
	/* argument is the task_struct */
	movel	sp@(4),a0

	/* save status register */
	movew	sr,a0@(LTS_TSS+LTSS_SR)

	/* save current alternate address space */
	movec	sfc,d0
	movew	d0,a0@(LTS_TSS+LTSS_FS)

	/* save non-scratch registers */
	moveml	d2-d7/a2-a7,a0@(LTS_TSS+LTSS_REGS)

	/* save floating point state */
	fsave	a0@(LTS_TSS+LTSS_FPSTATE)
	tstw	a0@(LTS_TSS+LTSS_FPSTATE)
	beq	1f	    /* NULL state, no need to save regs */
	fmovemx	fp0-fp7,a0@(LTS_TSS+LTSS_FPREGS)
	.long	0xf228bc00                                            
	.word	LTS_TSS+LTSS_FPCNTL
/*	fmovem	fpiar/fpcr/fpsr,a0@(LTS_TSS+LTSS_FPCNTL)*/

	rts


.globl _resume
	.even
_resume:
	/* current */
	movel	_current,a0

	/* save sr */
	movew	sr,a0@(LTS_TSS+LTSS_SR)

	/* disable interrupts */
	oriw	#0x0700,sr

	/* save fs (sfc,dfc) (may be pointing to kernel memory) */
	movec	sfc,d0
	movew	d0,a0@(LTS_TSS+LTSS_FS)

	/* save non-scratch registers */
	moveml	d2-d7/a2-a7,a0@(LTS_TSS+LTSS_REGS)

	/* save floating point state */
	fsave	a0@(LTS_TSS+LTSS_FPSTATE)
	tstw	a0@(LTS_TSS+LTSS_FPSTATE)
	beq	1f	    /* NULL state, no need to save regs */
	fmovemx fp0-fp7,a0@(LTS_TSS+LTSS_FPREGS)
	
	.long	0xf228bc00                                            
	.word	LTS_TSS+LTSS_FPCNTL
/*	fmovem	fpiar/fpcr/fpsr,a0@(LTS_TSS+LTSS_FPCNTL)*/
1:

	/* switch current task */
	movel	sp@(4),a0
	movel	a0,_current

	/* 68040 ? */
	movel	_boot_info+LBI_CPU,d1
	btst	#2,d1
	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@(LTS_TSS+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@(LTS_TSS+LTSS_CRP+4),d0
	.long	0x4e7b0806		/* movec d0,urp */


2:
	/* restore floating point unit state */
	tstw	a0@(LTS_TSS+LTSS_FPSTATE)
	beqs	1f	    /* NULL state; no need to load regs */
	fmovemx a0@(LTS_TSS+LTSS_FPREGS),fp0-fp7
	.long	0xf2289c00	            
	.word 	LTS_TSS+LTSS_FPCNTL
/*	fmovem	a0@(LTS_TSS+LTSS_FPCNTL),fpiar/fpcr/fpsr*/
1:
	frestore a0@(LTS_TSS+LTSS_FPSTATE)

	/* restore non-scratch registers */
	moveml	a0@(LTS_TSS+LTSS_REGS),d2-d7/a2-a7

	/* restore fs (sfc,dfc) */
	movew	a0@(LTS_TSS+LTSS_FS),a1
	movec	a1,sfc
	movec	a1,dfc

	/* restore status register */
	movew	a0@(LTS_TSS+LTSS_SR),sr

	rts

LC0:
	.ascii "sp for resumed task is %#lx (%#lx)"
	.byte 10,0
