162306a36Sopenharmony_ci|
262306a36Sopenharmony_ci|	skeleton.sa 3.2 4/26/91
362306a36Sopenharmony_ci|
462306a36Sopenharmony_ci|	This file contains code that is system dependent and will
562306a36Sopenharmony_ci|	need to be modified to install the FPSP.
662306a36Sopenharmony_ci|
762306a36Sopenharmony_ci|	Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
862306a36Sopenharmony_ci|	Put any target system specific handling that must be done immediately
962306a36Sopenharmony_ci|	before the jump instruction.  If there no handling necessary, then
1062306a36Sopenharmony_ci|	the 'fpsp_xxxx' handler entry point should be placed in the exception
1162306a36Sopenharmony_ci|	table so that the 'jmp' can be eliminated. If the FPSP determines that the
1262306a36Sopenharmony_ci|	exception is one that must be reported then there will be a
1362306a36Sopenharmony_ci|	return from the package by a 'jmp real_xxxx'.  At that point
1462306a36Sopenharmony_ci|	the machine state will be identical to the state before
1562306a36Sopenharmony_ci|	the FPSP was entered.  In particular, whatever condition
1662306a36Sopenharmony_ci|	that caused the exception will still be pending when the FPSP
1762306a36Sopenharmony_ci|	package returns.  Thus, there will be system specific code
1862306a36Sopenharmony_ci|	to handle the exception.
1962306a36Sopenharmony_ci|
2062306a36Sopenharmony_ci|	If the exception was completely handled by the package, then
2162306a36Sopenharmony_ci|	the return will be via a 'jmp fpsp_done'.  Unless there is
2262306a36Sopenharmony_ci|	OS specific work to be done (such as handling a context switch or
2362306a36Sopenharmony_ci|	interrupt) the user program can be resumed via 'rte'.
2462306a36Sopenharmony_ci|
2562306a36Sopenharmony_ci|	In the following skeleton code, some typical 'real_xxxx' handling
2662306a36Sopenharmony_ci|	code is shown.  This code may need to be moved to an appropriate
2762306a36Sopenharmony_ci|	place in the target system, or rewritten.
2862306a36Sopenharmony_ci|
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
3162306a36Sopenharmony_ci|			All Rights Reserved
3262306a36Sopenharmony_ci|
3362306a36Sopenharmony_ci|       For details on the license for this file, please see the
3462306a36Sopenharmony_ci|       file, README, in this same directory.
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci|
3762306a36Sopenharmony_ci|	Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
3862306a36Sopenharmony_ci|
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#include <linux/linkage.h>
4162306a36Sopenharmony_ci#include <asm/entry.h>
4262306a36Sopenharmony_ci#include <asm/asm-offsets.h>
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci|SKELETON	idnt    2,1 | Motorola 040 Floating Point Software Package
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	|section 15
4762306a36Sopenharmony_ci|
4862306a36Sopenharmony_ci|	The following counters are used for standalone testing
4962306a36Sopenharmony_ci|
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	|section 8
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#include "fpsp.h"
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	|xref	b1238_fix
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci|
5862306a36Sopenharmony_ci|	Divide by Zero exception
5962306a36Sopenharmony_ci|
6062306a36Sopenharmony_ci|	All dz exceptions are 'real', hence no fpsp_dz entry point.
6162306a36Sopenharmony_ci|
6262306a36Sopenharmony_ci	.global	dz
6362306a36Sopenharmony_ci	.global	real_dz
6462306a36Sopenharmony_cidz:
6562306a36Sopenharmony_cireal_dz:
6662306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
6762306a36Sopenharmony_ci	fsave		-(%sp)
6862306a36Sopenharmony_ci	bclrb		#E1,E_BYTE(%a6)
6962306a36Sopenharmony_ci	frestore	(%sp)+
7062306a36Sopenharmony_ci	unlk		%a6
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	SAVE_ALL_INT
7362306a36Sopenharmony_ci	GET_CURRENT(%d0)
7462306a36Sopenharmony_ci	movel	%sp,%sp@-		| stack frame pointer argument
7562306a36Sopenharmony_ci	bsrl	trap_c
7662306a36Sopenharmony_ci	addql	#4,%sp
7762306a36Sopenharmony_ci	bral	ret_from_exception
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci|
8062306a36Sopenharmony_ci|	Inexact exception
8162306a36Sopenharmony_ci|
8262306a36Sopenharmony_ci|	All inexact exceptions are real, but the 'real' handler
8362306a36Sopenharmony_ci|	will probably want to clear the pending exception.
8462306a36Sopenharmony_ci|	The provided code will clear the E3 exception (if pending),
8562306a36Sopenharmony_ci|	otherwise clear the E1 exception.  The frestore is not really
8662306a36Sopenharmony_ci|	necessary for E1 exceptions.
8762306a36Sopenharmony_ci|
8862306a36Sopenharmony_ci| Code following the 'inex' label is to handle bug #1232.  In this
8962306a36Sopenharmony_ci| bug, if an E1 snan, ovfl, or unfl occurred, and the process was
9062306a36Sopenharmony_ci| swapped out before taking the exception, the exception taken on
9162306a36Sopenharmony_ci| return was inex, rather than the correct exception.  The snan, ovfl,
9262306a36Sopenharmony_ci| and unfl exception to be taken must not have been enabled.  The
9362306a36Sopenharmony_ci| fix is to check for E1, and the existence of one of snan, ovfl,
9462306a36Sopenharmony_ci| or unfl bits set in the fpsr.  If any of these are set, branch
9562306a36Sopenharmony_ci| to the appropriate  handler for the exception in the fpsr.  Note
9662306a36Sopenharmony_ci| that this fix is only for d43b parts, and is skipped if the
9762306a36Sopenharmony_ci| version number is not $40.
9862306a36Sopenharmony_ci|
9962306a36Sopenharmony_ci|
10062306a36Sopenharmony_ci	.global	real_inex
10162306a36Sopenharmony_ci	.global	inex
10262306a36Sopenharmony_ciinex:
10362306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
10462306a36Sopenharmony_ci	fsave		-(%sp)
10562306a36Sopenharmony_ci	cmpib		#VER_40,(%sp)		|test version number
10662306a36Sopenharmony_ci	bnes		not_fmt40
10762306a36Sopenharmony_ci	fmovel		%fpsr,-(%sp)
10862306a36Sopenharmony_ci	btstb		#E1,E_BYTE(%a6)		|test for E1 set
10962306a36Sopenharmony_ci	beqs		not_b1232
11062306a36Sopenharmony_ci	btstb		#snan_bit,2(%sp) |test for snan
11162306a36Sopenharmony_ci	beq		inex_ckofl
11262306a36Sopenharmony_ci	addl		#4,%sp
11362306a36Sopenharmony_ci	frestore	(%sp)+
11462306a36Sopenharmony_ci	unlk		%a6
11562306a36Sopenharmony_ci	bra		snan
11662306a36Sopenharmony_ciinex_ckofl:
11762306a36Sopenharmony_ci	btstb		#ovfl_bit,2(%sp) |test for ovfl
11862306a36Sopenharmony_ci	beq		inex_ckufl
11962306a36Sopenharmony_ci	addl		#4,%sp
12062306a36Sopenharmony_ci	frestore	(%sp)+
12162306a36Sopenharmony_ci	unlk		%a6
12262306a36Sopenharmony_ci	bra		ovfl
12362306a36Sopenharmony_ciinex_ckufl:
12462306a36Sopenharmony_ci	btstb		#unfl_bit,2(%sp) |test for unfl
12562306a36Sopenharmony_ci	beq		not_b1232
12662306a36Sopenharmony_ci	addl		#4,%sp
12762306a36Sopenharmony_ci	frestore	(%sp)+
12862306a36Sopenharmony_ci	unlk		%a6
12962306a36Sopenharmony_ci	bra		unfl
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci|
13262306a36Sopenharmony_ci| We do not have the bug 1232 case.  Clean up the stack and call
13362306a36Sopenharmony_ci| real_inex.
13462306a36Sopenharmony_ci|
13562306a36Sopenharmony_cinot_b1232:
13662306a36Sopenharmony_ci	addl		#4,%sp
13762306a36Sopenharmony_ci	frestore	(%sp)+
13862306a36Sopenharmony_ci	unlk		%a6
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cireal_inex:
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
14362306a36Sopenharmony_ci	fsave		-(%sp)
14462306a36Sopenharmony_cinot_fmt40:
14562306a36Sopenharmony_ci	bclrb		#E3,E_BYTE(%a6)		|clear and test E3 flag
14662306a36Sopenharmony_ci	beqs		inex_cke1
14762306a36Sopenharmony_ci|
14862306a36Sopenharmony_ci| Clear dirty bit on dest resister in the frame before branching
14962306a36Sopenharmony_ci| to b1238_fix.
15062306a36Sopenharmony_ci|
15162306a36Sopenharmony_ci	moveml		%d0/%d1,USER_DA(%a6)
15262306a36Sopenharmony_ci	bfextu		CMDREG1B(%a6){#6:#3},%d0		|get dest reg no
15362306a36Sopenharmony_ci	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
15462306a36Sopenharmony_ci	bsrl		b1238_fix		|test for bug1238 case
15562306a36Sopenharmony_ci	moveml		USER_DA(%a6),%d0/%d1
15662306a36Sopenharmony_ci	bras		inex_done
15762306a36Sopenharmony_ciinex_cke1:
15862306a36Sopenharmony_ci	bclrb		#E1,E_BYTE(%a6)
15962306a36Sopenharmony_ciinex_done:
16062306a36Sopenharmony_ci	frestore	(%sp)+
16162306a36Sopenharmony_ci	unlk		%a6
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	SAVE_ALL_INT
16462306a36Sopenharmony_ci	GET_CURRENT(%d0)
16562306a36Sopenharmony_ci	movel	%sp,%sp@-		| stack frame pointer argument
16662306a36Sopenharmony_ci	bsrl	trap_c
16762306a36Sopenharmony_ci	addql	#4,%sp
16862306a36Sopenharmony_ci	bral	ret_from_exception
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci|
17162306a36Sopenharmony_ci|	Overflow exception
17262306a36Sopenharmony_ci|
17362306a36Sopenharmony_ci	|xref	fpsp_ovfl
17462306a36Sopenharmony_ci	.global	real_ovfl
17562306a36Sopenharmony_ci	.global	ovfl
17662306a36Sopenharmony_ciovfl:
17762306a36Sopenharmony_ci	jmp	fpsp_ovfl
17862306a36Sopenharmony_cireal_ovfl:
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
18162306a36Sopenharmony_ci	fsave		-(%sp)
18262306a36Sopenharmony_ci	bclrb		#E3,E_BYTE(%a6)		|clear and test E3 flag
18362306a36Sopenharmony_ci	bnes		ovfl_done
18462306a36Sopenharmony_ci	bclrb		#E1,E_BYTE(%a6)
18562306a36Sopenharmony_ciovfl_done:
18662306a36Sopenharmony_ci	frestore	(%sp)+
18762306a36Sopenharmony_ci	unlk		%a6
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	SAVE_ALL_INT
19062306a36Sopenharmony_ci	GET_CURRENT(%d0)
19162306a36Sopenharmony_ci	movel	%sp,%sp@-		| stack frame pointer argument
19262306a36Sopenharmony_ci	bsrl	trap_c
19362306a36Sopenharmony_ci	addql	#4,%sp
19462306a36Sopenharmony_ci	bral	ret_from_exception
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci|
19762306a36Sopenharmony_ci|	Underflow exception
19862306a36Sopenharmony_ci|
19962306a36Sopenharmony_ci	|xref	fpsp_unfl
20062306a36Sopenharmony_ci	.global	real_unfl
20162306a36Sopenharmony_ci	.global	unfl
20262306a36Sopenharmony_ciunfl:
20362306a36Sopenharmony_ci	jmp	fpsp_unfl
20462306a36Sopenharmony_cireal_unfl:
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
20762306a36Sopenharmony_ci	fsave		-(%sp)
20862306a36Sopenharmony_ci	bclrb		#E3,E_BYTE(%a6)		|clear and test E3 flag
20962306a36Sopenharmony_ci	bnes		unfl_done
21062306a36Sopenharmony_ci	bclrb		#E1,E_BYTE(%a6)
21162306a36Sopenharmony_ciunfl_done:
21262306a36Sopenharmony_ci	frestore	(%sp)+
21362306a36Sopenharmony_ci	unlk		%a6
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	SAVE_ALL_INT
21662306a36Sopenharmony_ci	GET_CURRENT(%d0)
21762306a36Sopenharmony_ci	movel	%sp,%sp@-		| stack frame pointer argument
21862306a36Sopenharmony_ci	bsrl	trap_c
21962306a36Sopenharmony_ci	addql	#4,%sp
22062306a36Sopenharmony_ci	bral	ret_from_exception
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci|
22362306a36Sopenharmony_ci|	Signalling NAN exception
22462306a36Sopenharmony_ci|
22562306a36Sopenharmony_ci	|xref	fpsp_snan
22662306a36Sopenharmony_ci	.global	real_snan
22762306a36Sopenharmony_ci	.global	snan
22862306a36Sopenharmony_cisnan:
22962306a36Sopenharmony_ci	jmp	fpsp_snan
23062306a36Sopenharmony_cireal_snan:
23162306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
23262306a36Sopenharmony_ci	fsave		-(%sp)
23362306a36Sopenharmony_ci	bclrb		#E1,E_BYTE(%a6)	|snan is always an E1 exception
23462306a36Sopenharmony_ci	frestore	(%sp)+
23562306a36Sopenharmony_ci	unlk		%a6
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	SAVE_ALL_INT
23862306a36Sopenharmony_ci	GET_CURRENT(%d0)
23962306a36Sopenharmony_ci	movel	%sp,%sp@-		| stack frame pointer argument
24062306a36Sopenharmony_ci	bsrl	trap_c
24162306a36Sopenharmony_ci	addql	#4,%sp
24262306a36Sopenharmony_ci	bral	ret_from_exception
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci|
24562306a36Sopenharmony_ci|	Operand Error exception
24662306a36Sopenharmony_ci|
24762306a36Sopenharmony_ci	|xref	fpsp_operr
24862306a36Sopenharmony_ci	.global	real_operr
24962306a36Sopenharmony_ci	.global	operr
25062306a36Sopenharmony_cioperr:
25162306a36Sopenharmony_ci	jmp	fpsp_operr
25262306a36Sopenharmony_cireal_operr:
25362306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
25462306a36Sopenharmony_ci	fsave		-(%sp)
25562306a36Sopenharmony_ci	bclrb		#E1,E_BYTE(%a6)	|operr is always an E1 exception
25662306a36Sopenharmony_ci	frestore	(%sp)+
25762306a36Sopenharmony_ci	unlk		%a6
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	SAVE_ALL_INT
26062306a36Sopenharmony_ci	GET_CURRENT(%d0)
26162306a36Sopenharmony_ci	movel	%sp,%sp@-		| stack frame pointer argument
26262306a36Sopenharmony_ci	bsrl	trap_c
26362306a36Sopenharmony_ci	addql	#4,%sp
26462306a36Sopenharmony_ci	bral	ret_from_exception
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci|
26862306a36Sopenharmony_ci|	BSUN exception
26962306a36Sopenharmony_ci|
27062306a36Sopenharmony_ci|	This sample handler simply clears the nan bit in the FPSR.
27162306a36Sopenharmony_ci|
27262306a36Sopenharmony_ci	|xref	fpsp_bsun
27362306a36Sopenharmony_ci	.global	real_bsun
27462306a36Sopenharmony_ci	.global	bsun
27562306a36Sopenharmony_cibsun:
27662306a36Sopenharmony_ci	jmp	fpsp_bsun
27762306a36Sopenharmony_cireal_bsun:
27862306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
27962306a36Sopenharmony_ci	fsave		-(%sp)
28062306a36Sopenharmony_ci	bclrb		#E1,E_BYTE(%a6)	|bsun is always an E1 exception
28162306a36Sopenharmony_ci	fmovel		%FPSR,-(%sp)
28262306a36Sopenharmony_ci	bclrb		#nan_bit,(%sp)
28362306a36Sopenharmony_ci	fmovel		(%sp)+,%FPSR
28462306a36Sopenharmony_ci	frestore	(%sp)+
28562306a36Sopenharmony_ci	unlk		%a6
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	SAVE_ALL_INT
28862306a36Sopenharmony_ci	GET_CURRENT(%d0)
28962306a36Sopenharmony_ci	movel	%sp,%sp@-		| stack frame pointer argument
29062306a36Sopenharmony_ci	bsrl	trap_c
29162306a36Sopenharmony_ci	addql	#4,%sp
29262306a36Sopenharmony_ci	bral	ret_from_exception
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci|
29562306a36Sopenharmony_ci|	F-line exception
29662306a36Sopenharmony_ci|
29762306a36Sopenharmony_ci|	A 'real' F-line exception is one that the FPSP isn't supposed to
29862306a36Sopenharmony_ci|	handle. E.g. an instruction with a co-processor ID that is not 1.
29962306a36Sopenharmony_ci|
30062306a36Sopenharmony_ci|
30162306a36Sopenharmony_ci	|xref	fpsp_fline
30262306a36Sopenharmony_ci	.global	real_fline
30362306a36Sopenharmony_ci	.global	fline
30462306a36Sopenharmony_cifline:
30562306a36Sopenharmony_ci	jmp	fpsp_fline
30662306a36Sopenharmony_cireal_fline:
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	SAVE_ALL_INT
30962306a36Sopenharmony_ci	GET_CURRENT(%d0)
31062306a36Sopenharmony_ci	movel	%sp,%sp@-		| stack frame pointer argument
31162306a36Sopenharmony_ci	bsrl	trap_c
31262306a36Sopenharmony_ci	addql	#4,%sp
31362306a36Sopenharmony_ci	bral	ret_from_exception
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci|
31662306a36Sopenharmony_ci|	Unsupported data type exception
31762306a36Sopenharmony_ci|
31862306a36Sopenharmony_ci	|xref	fpsp_unsupp
31962306a36Sopenharmony_ci	.global	real_unsupp
32062306a36Sopenharmony_ci	.global	unsupp
32162306a36Sopenharmony_ciunsupp:
32262306a36Sopenharmony_ci	jmp	fpsp_unsupp
32362306a36Sopenharmony_cireal_unsupp:
32462306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
32562306a36Sopenharmony_ci	fsave		-(%sp)
32662306a36Sopenharmony_ci	bclrb		#E1,E_BYTE(%a6)	|unsupp is always an E1 exception
32762306a36Sopenharmony_ci	frestore	(%sp)+
32862306a36Sopenharmony_ci	unlk		%a6
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	SAVE_ALL_INT
33162306a36Sopenharmony_ci	GET_CURRENT(%d0)
33262306a36Sopenharmony_ci	movel	%sp,%sp@-		| stack frame pointer argument
33362306a36Sopenharmony_ci	bsrl	trap_c
33462306a36Sopenharmony_ci	addql	#4,%sp
33562306a36Sopenharmony_ci	bral	ret_from_exception
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci|
33862306a36Sopenharmony_ci|	Trace exception
33962306a36Sopenharmony_ci|
34062306a36Sopenharmony_ci	.global	real_trace
34162306a36Sopenharmony_cireal_trace:
34262306a36Sopenharmony_ci	|
34362306a36Sopenharmony_ci	bral	trap
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci|
34662306a36Sopenharmony_ci|	fpsp_fmt_error --- exit point for frame format error
34762306a36Sopenharmony_ci|
34862306a36Sopenharmony_ci|	The fpu stack frame does not match the frames existing
34962306a36Sopenharmony_ci|	or planned at the time of this writing.  The fpsp is
35062306a36Sopenharmony_ci|	unable to handle frame sizes not in the following
35162306a36Sopenharmony_ci|	version:size pairs:
35262306a36Sopenharmony_ci|
35362306a36Sopenharmony_ci|	{4060, 4160} - busy frame
35462306a36Sopenharmony_ci|	{4028, 4130} - unimp frame
35562306a36Sopenharmony_ci|	{4000, 4100} - idle frame
35662306a36Sopenharmony_ci|
35762306a36Sopenharmony_ci|	This entry point simply holds an f-line illegal value.
35862306a36Sopenharmony_ci|	Replace this with a call to your kernel panic code or
35962306a36Sopenharmony_ci|	code to handle future revisions of the fpu.
36062306a36Sopenharmony_ci|
36162306a36Sopenharmony_ci	.global	fpsp_fmt_error
36262306a36Sopenharmony_cifpsp_fmt_error:
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	.long	0xf27f0000	|f-line illegal
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci|
36762306a36Sopenharmony_ci|	fpsp_done --- FPSP exit point
36862306a36Sopenharmony_ci|
36962306a36Sopenharmony_ci|	The exception has been handled by the package and we are ready
37062306a36Sopenharmony_ci|	to return to user mode, but there may be OS specific code
37162306a36Sopenharmony_ci|	to execute before we do.  If there is, do it now.
37262306a36Sopenharmony_ci|
37362306a36Sopenharmony_ci|
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	.global	fpsp_done
37662306a36Sopenharmony_cifpsp_done:
37762306a36Sopenharmony_ci	btst	#0x5,%sp@		| supervisor bit set in saved SR?
37862306a36Sopenharmony_ci	beq	.Lnotkern
37962306a36Sopenharmony_ci	rte
38062306a36Sopenharmony_ci.Lnotkern:
38162306a36Sopenharmony_ci	SAVE_ALL_INT
38262306a36Sopenharmony_ci	GET_CURRENT(%d0)
38362306a36Sopenharmony_ci	| deliver signals, reschedule etc..
38462306a36Sopenharmony_ci	jra	ret_from_exception
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci|
38762306a36Sopenharmony_ci|	mem_write --- write to user or supervisor address space
38862306a36Sopenharmony_ci|
38962306a36Sopenharmony_ci| Writes to memory while in supervisor mode.  copyout accomplishes
39062306a36Sopenharmony_ci| this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
39162306a36Sopenharmony_ci| If you don't have copyout, use the local copy of the function below.
39262306a36Sopenharmony_ci|
39362306a36Sopenharmony_ci|	a0 - supervisor source address
39462306a36Sopenharmony_ci|	a1 - user destination address
39562306a36Sopenharmony_ci|	d0 - number of bytes to write (maximum count is 12)
39662306a36Sopenharmony_ci|
39762306a36Sopenharmony_ci| The supervisor source address is guaranteed to point into the supervisor
39862306a36Sopenharmony_ci| stack.  The result is that a UNIX
39962306a36Sopenharmony_ci| process is allowed to sleep as a consequence of a page fault during
40062306a36Sopenharmony_ci| copyout.  The probability of a page fault is exceedingly small because
40162306a36Sopenharmony_ci| the 68040 always reads the destination address and thus the page
40262306a36Sopenharmony_ci| faults should have already been handled.
40362306a36Sopenharmony_ci|
40462306a36Sopenharmony_ci| If the EXC_SR shows that the exception was from supervisor space,
40562306a36Sopenharmony_ci| then just do a dumb (and slow) memory move.  In a UNIX environment
40662306a36Sopenharmony_ci| there shouldn't be any supervisor mode floating point exceptions.
40762306a36Sopenharmony_ci|
40862306a36Sopenharmony_ci	.global	mem_write
40962306a36Sopenharmony_cimem_write:
41062306a36Sopenharmony_ci	btstb	#5,EXC_SR(%a6)	|check for supervisor state
41162306a36Sopenharmony_ci	beqs	user_write
41262306a36Sopenharmony_cisuper_write:
41362306a36Sopenharmony_ci	moveb	(%a0)+,(%a1)+
41462306a36Sopenharmony_ci	subql	#1,%d0
41562306a36Sopenharmony_ci	bnes	super_write
41662306a36Sopenharmony_ci	rts
41762306a36Sopenharmony_ciuser_write:
41862306a36Sopenharmony_ci	movel	%d1,-(%sp)	|preserve d1 just in case
41962306a36Sopenharmony_ci	movel	%d0,-(%sp)
42062306a36Sopenharmony_ci	movel	%a1,-(%sp)
42162306a36Sopenharmony_ci	movel	%a0,-(%sp)
42262306a36Sopenharmony_ci	jsr		copyout
42362306a36Sopenharmony_ci	addw	#12,%sp
42462306a36Sopenharmony_ci	movel	(%sp)+,%d1
42562306a36Sopenharmony_ci	rts
42662306a36Sopenharmony_ci|
42762306a36Sopenharmony_ci|	mem_read --- read from user or supervisor address space
42862306a36Sopenharmony_ci|
42962306a36Sopenharmony_ci| Reads from memory while in supervisor mode.  copyin accomplishes
43062306a36Sopenharmony_ci| this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
43162306a36Sopenharmony_ci| If you don't have copyin, use the local copy of the function below.
43262306a36Sopenharmony_ci|
43362306a36Sopenharmony_ci| The FPSP calls mem_read to read the original F-line instruction in order
43462306a36Sopenharmony_ci| to extract the data register number when the 'Dn' addressing mode is
43562306a36Sopenharmony_ci| used.
43662306a36Sopenharmony_ci|
43762306a36Sopenharmony_ci|Input:
43862306a36Sopenharmony_ci|	a0 - user source address
43962306a36Sopenharmony_ci|	a1 - supervisor destination address
44062306a36Sopenharmony_ci|	d0 - number of bytes to read (maximum count is 12)
44162306a36Sopenharmony_ci|
44262306a36Sopenharmony_ci| Like mem_write, mem_read always reads with a supervisor
44362306a36Sopenharmony_ci| destination address on the supervisor stack.  Also like mem_write,
44462306a36Sopenharmony_ci| the EXC_SR is checked and a simple memory copy is done if reading
44562306a36Sopenharmony_ci| from supervisor space is indicated.
44662306a36Sopenharmony_ci|
44762306a36Sopenharmony_ci	.global	mem_read
44862306a36Sopenharmony_cimem_read:
44962306a36Sopenharmony_ci	btstb	#5,EXC_SR(%a6)	|check for supervisor state
45062306a36Sopenharmony_ci	beqs	user_read
45162306a36Sopenharmony_cisuper_read:
45262306a36Sopenharmony_ci	moveb	(%a0)+,(%a1)+
45362306a36Sopenharmony_ci	subql	#1,%d0
45462306a36Sopenharmony_ci	bnes	super_read
45562306a36Sopenharmony_ci	rts
45662306a36Sopenharmony_ciuser_read:
45762306a36Sopenharmony_ci	movel	%d1,-(%sp)	|preserve d1 just in case
45862306a36Sopenharmony_ci	movel	%d0,-(%sp)
45962306a36Sopenharmony_ci	movel	%a1,-(%sp)
46062306a36Sopenharmony_ci	movel	%a0,-(%sp)
46162306a36Sopenharmony_ci	jsr	copyin
46262306a36Sopenharmony_ci	addw	#12,%sp
46362306a36Sopenharmony_ci	movel	(%sp)+,%d1
46462306a36Sopenharmony_ci	rts
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci|
46762306a36Sopenharmony_ci| Use these routines if your kernel doesn't have copyout/copyin equivalents.
46862306a36Sopenharmony_ci| Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
46962306a36Sopenharmony_ci| and copyin overwrites SFC.
47062306a36Sopenharmony_ci|
47162306a36Sopenharmony_cicopyout:
47262306a36Sopenharmony_ci	movel	4(%sp),%a0	| source
47362306a36Sopenharmony_ci	movel	8(%sp),%a1	| destination
47462306a36Sopenharmony_ci	movel	12(%sp),%d0	| count
47562306a36Sopenharmony_ci	subl	#1,%d0		| dec count by 1 for dbra
47662306a36Sopenharmony_ci	movel	#1,%d1
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci|	DFC is already set
47962306a36Sopenharmony_ci|	movec	%d1,%DFC		| set dfc for user data space
48062306a36Sopenharmony_cimoreout:
48162306a36Sopenharmony_ci	moveb	(%a0)+,%d1	| fetch supervisor byte
48262306a36Sopenharmony_ciout_ea:
48362306a36Sopenharmony_ci	movesb	%d1,(%a1)+	| write user byte
48462306a36Sopenharmony_ci	dbf	%d0,moreout
48562306a36Sopenharmony_ci	rts
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cicopyin:
48862306a36Sopenharmony_ci	movel	4(%sp),%a0	| source
48962306a36Sopenharmony_ci	movel	8(%sp),%a1	| destination
49062306a36Sopenharmony_ci	movel	12(%sp),%d0	| count
49162306a36Sopenharmony_ci	subl	#1,%d0		| dec count by 1 for dbra
49262306a36Sopenharmony_ci	movel	#1,%d1
49362306a36Sopenharmony_ci|	SFC is already set
49462306a36Sopenharmony_ci|	movec	%d1,%SFC		| set sfc for user space
49562306a36Sopenharmony_cimorein:
49662306a36Sopenharmony_ciin_ea:
49762306a36Sopenharmony_ci	movesb	(%a0)+,%d1	| fetch user byte
49862306a36Sopenharmony_ci	moveb	%d1,(%a1)+	| write supervisor byte
49962306a36Sopenharmony_ci	dbf	%d0,morein
50062306a36Sopenharmony_ci	rts
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	.section .fixup,"ax"
50362306a36Sopenharmony_ci	.even
50462306a36Sopenharmony_ci1:
50562306a36Sopenharmony_ci	jbsr	fpsp040_die
50662306a36Sopenharmony_ci	jbra	.Lnotkern
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	.section __ex_table,"a"
50962306a36Sopenharmony_ci	.align	4
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	.long	in_ea,1b
51262306a36Sopenharmony_ci	.long	out_ea,1b
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	|end
515