xref: /openbmc/linux/arch/m68k/fpsp040/skeleton.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
11da177e4SLinus Torvalds|
21da177e4SLinus Torvalds|	skeleton.sa 3.2 4/26/91
31da177e4SLinus Torvalds|
41da177e4SLinus Torvalds|	This file contains code that is system dependent and will
51da177e4SLinus Torvalds|	need to be modified to install the FPSP.
61da177e4SLinus Torvalds|
71da177e4SLinus Torvalds|	Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
81da177e4SLinus Torvalds|	Put any target system specific handling that must be done immediately
91da177e4SLinus Torvalds|	before the jump instruction.  If there no handling necessary, then
101da177e4SLinus Torvalds|	the 'fpsp_xxxx' handler entry point should be placed in the exception
111da177e4SLinus Torvalds|	table so that the 'jmp' can be eliminated. If the FPSP determines that the
121da177e4SLinus Torvalds|	exception is one that must be reported then there will be a
131da177e4SLinus Torvalds|	return from the package by a 'jmp real_xxxx'.  At that point
141da177e4SLinus Torvalds|	the machine state will be identical to the state before
151da177e4SLinus Torvalds|	the FPSP was entered.  In particular, whatever condition
161da177e4SLinus Torvalds|	that caused the exception will still be pending when the FPSP
171da177e4SLinus Torvalds|	package returns.  Thus, there will be system specific code
181da177e4SLinus Torvalds|	to handle the exception.
191da177e4SLinus Torvalds|
201da177e4SLinus Torvalds|	If the exception was completely handled by the package, then
211da177e4SLinus Torvalds|	the return will be via a 'jmp fpsp_done'.  Unless there is
221da177e4SLinus Torvalds|	OS specific work to be done (such as handling a context switch or
231da177e4SLinus Torvalds|	interrupt) the user program can be resumed via 'rte'.
241da177e4SLinus Torvalds|
251da177e4SLinus Torvalds|	In the following skeleton code, some typical 'real_xxxx' handling
261da177e4SLinus Torvalds|	code is shown.  This code may need to be moved to an appropriate
271da177e4SLinus Torvalds|	place in the target system, or rewritten.
281da177e4SLinus Torvalds|
291da177e4SLinus Torvalds
301da177e4SLinus Torvalds|		Copyright (C) Motorola, Inc. 1990
311da177e4SLinus Torvalds|			All Rights Reserved
321da177e4SLinus Torvalds|
33e00d82d0SMatt Waddel|       For details on the license for this file, please see the
34e00d82d0SMatt Waddel|       file, README, in this same directory.
351da177e4SLinus Torvalds
361da177e4SLinus Torvalds|
371da177e4SLinus Torvalds|	Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
381da177e4SLinus Torvalds|
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds#include <linux/linkage.h>
411da177e4SLinus Torvalds#include <asm/entry.h>
420013a854SSam Ravnborg#include <asm/asm-offsets.h>
431da177e4SLinus Torvalds
441da177e4SLinus Torvalds|SKELETON	idnt    2,1 | Motorola 040 Floating Point Software Package
451da177e4SLinus Torvalds
461da177e4SLinus Torvalds	|section 15
471da177e4SLinus Torvalds|
481da177e4SLinus Torvalds|	The following counters are used for standalone testing
491da177e4SLinus Torvalds|
501da177e4SLinus Torvalds
511da177e4SLinus Torvalds	|section 8
521da177e4SLinus Torvalds
531da177e4SLinus Torvalds#include "fpsp.h"
541da177e4SLinus Torvalds
551da177e4SLinus Torvalds	|xref	b1238_fix
561da177e4SLinus Torvalds
571da177e4SLinus Torvalds|
581da177e4SLinus Torvalds|	Divide by Zero exception
591da177e4SLinus Torvalds|
601da177e4SLinus Torvalds|	All dz exceptions are 'real', hence no fpsp_dz entry point.
611da177e4SLinus Torvalds|
621da177e4SLinus Torvalds	.global	dz
631da177e4SLinus Torvalds	.global	real_dz
641da177e4SLinus Torvaldsdz:
651da177e4SLinus Torvaldsreal_dz:
661da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
671da177e4SLinus Torvalds	fsave		-(%sp)
681da177e4SLinus Torvalds	bclrb		#E1,E_BYTE(%a6)
691da177e4SLinus Torvalds	frestore	(%sp)+
701da177e4SLinus Torvalds	unlk		%a6
711da177e4SLinus Torvalds
721da177e4SLinus Torvalds	SAVE_ALL_INT
731da177e4SLinus Torvalds	GET_CURRENT(%d0)
741da177e4SLinus Torvalds	movel	%sp,%sp@-		| stack frame pointer argument
751da177e4SLinus Torvalds	bsrl	trap_c
761da177e4SLinus Torvalds	addql	#4,%sp
771da177e4SLinus Torvalds	bral	ret_from_exception
781da177e4SLinus Torvalds
791da177e4SLinus Torvalds|
801da177e4SLinus Torvalds|	Inexact exception
811da177e4SLinus Torvalds|
821da177e4SLinus Torvalds|	All inexact exceptions are real, but the 'real' handler
831da177e4SLinus Torvalds|	will probably want to clear the pending exception.
841da177e4SLinus Torvalds|	The provided code will clear the E3 exception (if pending),
851da177e4SLinus Torvalds|	otherwise clear the E1 exception.  The frestore is not really
861da177e4SLinus Torvalds|	necessary for E1 exceptions.
871da177e4SLinus Torvalds|
881da177e4SLinus Torvalds| Code following the 'inex' label is to handle bug #1232.  In this
891da177e4SLinus Torvalds| bug, if an E1 snan, ovfl, or unfl occurred, and the process was
901da177e4SLinus Torvalds| swapped out before taking the exception, the exception taken on
911da177e4SLinus Torvalds| return was inex, rather than the correct exception.  The snan, ovfl,
921da177e4SLinus Torvalds| and unfl exception to be taken must not have been enabled.  The
931da177e4SLinus Torvalds| fix is to check for E1, and the existence of one of snan, ovfl,
941da177e4SLinus Torvalds| or unfl bits set in the fpsr.  If any of these are set, branch
951da177e4SLinus Torvalds| to the appropriate  handler for the exception in the fpsr.  Note
961da177e4SLinus Torvalds| that this fix is only for d43b parts, and is skipped if the
971da177e4SLinus Torvalds| version number is not $40.
981da177e4SLinus Torvalds|
991da177e4SLinus Torvalds|
1001da177e4SLinus Torvalds	.global	real_inex
1011da177e4SLinus Torvalds	.global	inex
1021da177e4SLinus Torvaldsinex:
1031da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
1041da177e4SLinus Torvalds	fsave		-(%sp)
1051da177e4SLinus Torvalds	cmpib		#VER_40,(%sp)		|test version number
1061da177e4SLinus Torvalds	bnes		not_fmt40
1071da177e4SLinus Torvalds	fmovel		%fpsr,-(%sp)
1081da177e4SLinus Torvalds	btstb		#E1,E_BYTE(%a6)		|test for E1 set
1091da177e4SLinus Torvalds	beqs		not_b1232
1101da177e4SLinus Torvalds	btstb		#snan_bit,2(%sp) |test for snan
1111da177e4SLinus Torvalds	beq		inex_ckofl
1121da177e4SLinus Torvalds	addl		#4,%sp
1131da177e4SLinus Torvalds	frestore	(%sp)+
1141da177e4SLinus Torvalds	unlk		%a6
1151da177e4SLinus Torvalds	bra		snan
1161da177e4SLinus Torvaldsinex_ckofl:
1171da177e4SLinus Torvalds	btstb		#ovfl_bit,2(%sp) |test for ovfl
1181da177e4SLinus Torvalds	beq		inex_ckufl
1191da177e4SLinus Torvalds	addl		#4,%sp
1201da177e4SLinus Torvalds	frestore	(%sp)+
1211da177e4SLinus Torvalds	unlk		%a6
1221da177e4SLinus Torvalds	bra		ovfl
1231da177e4SLinus Torvaldsinex_ckufl:
1241da177e4SLinus Torvalds	btstb		#unfl_bit,2(%sp) |test for unfl
1251da177e4SLinus Torvalds	beq		not_b1232
1261da177e4SLinus Torvalds	addl		#4,%sp
1271da177e4SLinus Torvalds	frestore	(%sp)+
1281da177e4SLinus Torvalds	unlk		%a6
1291da177e4SLinus Torvalds	bra		unfl
1301da177e4SLinus Torvalds
1311da177e4SLinus Torvalds|
1321da177e4SLinus Torvalds| We do not have the bug 1232 case.  Clean up the stack and call
1331da177e4SLinus Torvalds| real_inex.
1341da177e4SLinus Torvalds|
1351da177e4SLinus Torvaldsnot_b1232:
1361da177e4SLinus Torvalds	addl		#4,%sp
1371da177e4SLinus Torvalds	frestore	(%sp)+
1381da177e4SLinus Torvalds	unlk		%a6
1391da177e4SLinus Torvalds
1401da177e4SLinus Torvaldsreal_inex:
1411da177e4SLinus Torvalds
1421da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
1431da177e4SLinus Torvalds	fsave		-(%sp)
1441da177e4SLinus Torvaldsnot_fmt40:
1451da177e4SLinus Torvalds	bclrb		#E3,E_BYTE(%a6)		|clear and test E3 flag
1461da177e4SLinus Torvalds	beqs		inex_cke1
1471da177e4SLinus Torvalds|
1481da177e4SLinus Torvalds| Clear dirty bit on dest resister in the frame before branching
1491da177e4SLinus Torvalds| to b1238_fix.
1501da177e4SLinus Torvalds|
1511da177e4SLinus Torvalds	moveml		%d0/%d1,USER_DA(%a6)
1521da177e4SLinus Torvalds	bfextu		CMDREG1B(%a6){#6:#3},%d0		|get dest reg no
1531da177e4SLinus Torvalds	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
1541da177e4SLinus Torvalds	bsrl		b1238_fix		|test for bug1238 case
1551da177e4SLinus Torvalds	moveml		USER_DA(%a6),%d0/%d1
1561da177e4SLinus Torvalds	bras		inex_done
1571da177e4SLinus Torvaldsinex_cke1:
1581da177e4SLinus Torvalds	bclrb		#E1,E_BYTE(%a6)
1591da177e4SLinus Torvaldsinex_done:
1601da177e4SLinus Torvalds	frestore	(%sp)+
1611da177e4SLinus Torvalds	unlk		%a6
1621da177e4SLinus Torvalds
1631da177e4SLinus Torvalds	SAVE_ALL_INT
1641da177e4SLinus Torvalds	GET_CURRENT(%d0)
1651da177e4SLinus Torvalds	movel	%sp,%sp@-		| stack frame pointer argument
1661da177e4SLinus Torvalds	bsrl	trap_c
1671da177e4SLinus Torvalds	addql	#4,%sp
1681da177e4SLinus Torvalds	bral	ret_from_exception
1691da177e4SLinus Torvalds
1701da177e4SLinus Torvalds|
1711da177e4SLinus Torvalds|	Overflow exception
1721da177e4SLinus Torvalds|
1731da177e4SLinus Torvalds	|xref	fpsp_ovfl
1741da177e4SLinus Torvalds	.global	real_ovfl
1751da177e4SLinus Torvalds	.global	ovfl
1761da177e4SLinus Torvaldsovfl:
1771da177e4SLinus Torvalds	jmp	fpsp_ovfl
1781da177e4SLinus Torvaldsreal_ovfl:
1791da177e4SLinus Torvalds
1801da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
1811da177e4SLinus Torvalds	fsave		-(%sp)
1821da177e4SLinus Torvalds	bclrb		#E3,E_BYTE(%a6)		|clear and test E3 flag
1831da177e4SLinus Torvalds	bnes		ovfl_done
1841da177e4SLinus Torvalds	bclrb		#E1,E_BYTE(%a6)
1851da177e4SLinus Torvaldsovfl_done:
1861da177e4SLinus Torvalds	frestore	(%sp)+
1871da177e4SLinus Torvalds	unlk		%a6
1881da177e4SLinus Torvalds
1891da177e4SLinus Torvalds	SAVE_ALL_INT
1901da177e4SLinus Torvalds	GET_CURRENT(%d0)
1911da177e4SLinus Torvalds	movel	%sp,%sp@-		| stack frame pointer argument
1921da177e4SLinus Torvalds	bsrl	trap_c
1931da177e4SLinus Torvalds	addql	#4,%sp
1941da177e4SLinus Torvalds	bral	ret_from_exception
1951da177e4SLinus Torvalds
1961da177e4SLinus Torvalds|
1971da177e4SLinus Torvalds|	Underflow exception
1981da177e4SLinus Torvalds|
1991da177e4SLinus Torvalds	|xref	fpsp_unfl
2001da177e4SLinus Torvalds	.global	real_unfl
2011da177e4SLinus Torvalds	.global	unfl
2021da177e4SLinus Torvaldsunfl:
2031da177e4SLinus Torvalds	jmp	fpsp_unfl
2041da177e4SLinus Torvaldsreal_unfl:
2051da177e4SLinus Torvalds
2061da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
2071da177e4SLinus Torvalds	fsave		-(%sp)
2081da177e4SLinus Torvalds	bclrb		#E3,E_BYTE(%a6)		|clear and test E3 flag
2091da177e4SLinus Torvalds	bnes		unfl_done
2101da177e4SLinus Torvalds	bclrb		#E1,E_BYTE(%a6)
2111da177e4SLinus Torvaldsunfl_done:
2121da177e4SLinus Torvalds	frestore	(%sp)+
2131da177e4SLinus Torvalds	unlk		%a6
2141da177e4SLinus Torvalds
2151da177e4SLinus Torvalds	SAVE_ALL_INT
2161da177e4SLinus Torvalds	GET_CURRENT(%d0)
2171da177e4SLinus Torvalds	movel	%sp,%sp@-		| stack frame pointer argument
2181da177e4SLinus Torvalds	bsrl	trap_c
2191da177e4SLinus Torvalds	addql	#4,%sp
2201da177e4SLinus Torvalds	bral	ret_from_exception
2211da177e4SLinus Torvalds
2221da177e4SLinus Torvalds|
2231da177e4SLinus Torvalds|	Signalling NAN exception
2241da177e4SLinus Torvalds|
2251da177e4SLinus Torvalds	|xref	fpsp_snan
2261da177e4SLinus Torvalds	.global	real_snan
2271da177e4SLinus Torvalds	.global	snan
2281da177e4SLinus Torvaldssnan:
2291da177e4SLinus Torvalds	jmp	fpsp_snan
2301da177e4SLinus Torvaldsreal_snan:
2311da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
2321da177e4SLinus Torvalds	fsave		-(%sp)
2331da177e4SLinus Torvalds	bclrb		#E1,E_BYTE(%a6)	|snan is always an E1 exception
2341da177e4SLinus Torvalds	frestore	(%sp)+
2351da177e4SLinus Torvalds	unlk		%a6
2361da177e4SLinus Torvalds
2371da177e4SLinus Torvalds	SAVE_ALL_INT
2381da177e4SLinus Torvalds	GET_CURRENT(%d0)
2391da177e4SLinus Torvalds	movel	%sp,%sp@-		| stack frame pointer argument
2401da177e4SLinus Torvalds	bsrl	trap_c
2411da177e4SLinus Torvalds	addql	#4,%sp
2421da177e4SLinus Torvalds	bral	ret_from_exception
2431da177e4SLinus Torvalds
2441da177e4SLinus Torvalds|
2451da177e4SLinus Torvalds|	Operand Error exception
2461da177e4SLinus Torvalds|
2471da177e4SLinus Torvalds	|xref	fpsp_operr
2481da177e4SLinus Torvalds	.global	real_operr
2491da177e4SLinus Torvalds	.global	operr
2501da177e4SLinus Torvaldsoperr:
2511da177e4SLinus Torvalds	jmp	fpsp_operr
2521da177e4SLinus Torvaldsreal_operr:
2531da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
2541da177e4SLinus Torvalds	fsave		-(%sp)
2551da177e4SLinus Torvalds	bclrb		#E1,E_BYTE(%a6)	|operr is always an E1 exception
2561da177e4SLinus Torvalds	frestore	(%sp)+
2571da177e4SLinus Torvalds	unlk		%a6
2581da177e4SLinus Torvalds
2591da177e4SLinus Torvalds	SAVE_ALL_INT
2601da177e4SLinus Torvalds	GET_CURRENT(%d0)
2611da177e4SLinus Torvalds	movel	%sp,%sp@-		| stack frame pointer argument
2621da177e4SLinus Torvalds	bsrl	trap_c
2631da177e4SLinus Torvalds	addql	#4,%sp
2641da177e4SLinus Torvalds	bral	ret_from_exception
2651da177e4SLinus Torvalds
2661da177e4SLinus Torvalds
2671da177e4SLinus Torvalds|
2681da177e4SLinus Torvalds|	BSUN exception
2691da177e4SLinus Torvalds|
2701da177e4SLinus Torvalds|	This sample handler simply clears the nan bit in the FPSR.
2711da177e4SLinus Torvalds|
2721da177e4SLinus Torvalds	|xref	fpsp_bsun
2731da177e4SLinus Torvalds	.global	real_bsun
2741da177e4SLinus Torvalds	.global	bsun
2751da177e4SLinus Torvaldsbsun:
2761da177e4SLinus Torvalds	jmp	fpsp_bsun
2771da177e4SLinus Torvaldsreal_bsun:
2781da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
2791da177e4SLinus Torvalds	fsave		-(%sp)
2801da177e4SLinus Torvalds	bclrb		#E1,E_BYTE(%a6)	|bsun is always an E1 exception
2811da177e4SLinus Torvalds	fmovel		%FPSR,-(%sp)
2821da177e4SLinus Torvalds	bclrb		#nan_bit,(%sp)
2831da177e4SLinus Torvalds	fmovel		(%sp)+,%FPSR
2841da177e4SLinus Torvalds	frestore	(%sp)+
2851da177e4SLinus Torvalds	unlk		%a6
2861da177e4SLinus Torvalds
2871da177e4SLinus Torvalds	SAVE_ALL_INT
2881da177e4SLinus Torvalds	GET_CURRENT(%d0)
2891da177e4SLinus Torvalds	movel	%sp,%sp@-		| stack frame pointer argument
2901da177e4SLinus Torvalds	bsrl	trap_c
2911da177e4SLinus Torvalds	addql	#4,%sp
2921da177e4SLinus Torvalds	bral	ret_from_exception
2931da177e4SLinus Torvalds
2941da177e4SLinus Torvalds|
2951da177e4SLinus Torvalds|	F-line exception
2961da177e4SLinus Torvalds|
2971da177e4SLinus Torvalds|	A 'real' F-line exception is one that the FPSP isn't supposed to
2981da177e4SLinus Torvalds|	handle. E.g. an instruction with a co-processor ID that is not 1.
2991da177e4SLinus Torvalds|
3001da177e4SLinus Torvalds|
3011da177e4SLinus Torvalds	|xref	fpsp_fline
3021da177e4SLinus Torvalds	.global	real_fline
3031da177e4SLinus Torvalds	.global	fline
3041da177e4SLinus Torvaldsfline:
3051da177e4SLinus Torvalds	jmp	fpsp_fline
3061da177e4SLinus Torvaldsreal_fline:
3071da177e4SLinus Torvalds
3081da177e4SLinus Torvalds	SAVE_ALL_INT
3091da177e4SLinus Torvalds	GET_CURRENT(%d0)
3101da177e4SLinus Torvalds	movel	%sp,%sp@-		| stack frame pointer argument
3111da177e4SLinus Torvalds	bsrl	trap_c
3121da177e4SLinus Torvalds	addql	#4,%sp
3131da177e4SLinus Torvalds	bral	ret_from_exception
3141da177e4SLinus Torvalds
3151da177e4SLinus Torvalds|
3161da177e4SLinus Torvalds|	Unsupported data type exception
3171da177e4SLinus Torvalds|
3181da177e4SLinus Torvalds	|xref	fpsp_unsupp
3191da177e4SLinus Torvalds	.global	real_unsupp
3201da177e4SLinus Torvalds	.global	unsupp
3211da177e4SLinus Torvaldsunsupp:
3221da177e4SLinus Torvalds	jmp	fpsp_unsupp
3231da177e4SLinus Torvaldsreal_unsupp:
3241da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
3251da177e4SLinus Torvalds	fsave		-(%sp)
3261da177e4SLinus Torvalds	bclrb		#E1,E_BYTE(%a6)	|unsupp is always an E1 exception
3271da177e4SLinus Torvalds	frestore	(%sp)+
3281da177e4SLinus Torvalds	unlk		%a6
3291da177e4SLinus Torvalds
3301da177e4SLinus Torvalds	SAVE_ALL_INT
3311da177e4SLinus Torvalds	GET_CURRENT(%d0)
3321da177e4SLinus Torvalds	movel	%sp,%sp@-		| stack frame pointer argument
3331da177e4SLinus Torvalds	bsrl	trap_c
3341da177e4SLinus Torvalds	addql	#4,%sp
3351da177e4SLinus Torvalds	bral	ret_from_exception
3361da177e4SLinus Torvalds
3371da177e4SLinus Torvalds|
3381da177e4SLinus Torvalds|	Trace exception
3391da177e4SLinus Torvalds|
3401da177e4SLinus Torvalds	.global	real_trace
3411da177e4SLinus Torvaldsreal_trace:
3421da177e4SLinus Torvalds	|
3431da177e4SLinus Torvalds	bral	trap
3441da177e4SLinus Torvalds
3451da177e4SLinus Torvalds|
3461da177e4SLinus Torvalds|	fpsp_fmt_error --- exit point for frame format error
3471da177e4SLinus Torvalds|
3481da177e4SLinus Torvalds|	The fpu stack frame does not match the frames existing
3491da177e4SLinus Torvalds|	or planned at the time of this writing.  The fpsp is
3501da177e4SLinus Torvalds|	unable to handle frame sizes not in the following
3511da177e4SLinus Torvalds|	version:size pairs:
3521da177e4SLinus Torvalds|
3531da177e4SLinus Torvalds|	{4060, 4160} - busy frame
3541da177e4SLinus Torvalds|	{4028, 4130} - unimp frame
3551da177e4SLinus Torvalds|	{4000, 4100} - idle frame
3561da177e4SLinus Torvalds|
3571da177e4SLinus Torvalds|	This entry point simply holds an f-line illegal value.
3581da177e4SLinus Torvalds|	Replace this with a call to your kernel panic code or
3591da177e4SLinus Torvalds|	code to handle future revisions of the fpu.
3601da177e4SLinus Torvalds|
3611da177e4SLinus Torvalds	.global	fpsp_fmt_error
3621da177e4SLinus Torvaldsfpsp_fmt_error:
3631da177e4SLinus Torvalds
3641da177e4SLinus Torvalds	.long	0xf27f0000	|f-line illegal
3651da177e4SLinus Torvalds
3661da177e4SLinus Torvalds|
3671da177e4SLinus Torvalds|	fpsp_done --- FPSP exit point
3681da177e4SLinus Torvalds|
3691da177e4SLinus Torvalds|	The exception has been handled by the package and we are ready
3701da177e4SLinus Torvalds|	to return to user mode, but there may be OS specific code
3711da177e4SLinus Torvalds|	to execute before we do.  If there is, do it now.
3721da177e4SLinus Torvalds|
3731da177e4SLinus Torvalds|
3741da177e4SLinus Torvalds
3751da177e4SLinus Torvalds	.global	fpsp_done
3761da177e4SLinus Torvaldsfpsp_done:
3771da177e4SLinus Torvalds	btst	#0x5,%sp@		| supervisor bit set in saved SR?
3781da177e4SLinus Torvalds	beq	.Lnotkern
3791da177e4SLinus Torvalds	rte
3801da177e4SLinus Torvalds.Lnotkern:
3811da177e4SLinus Torvalds	SAVE_ALL_INT
3821da177e4SLinus Torvalds	GET_CURRENT(%d0)
3833b66a1edSRoman Zippel	| deliver signals, reschedule etc..
3843b66a1edSRoman Zippel	jra	ret_from_exception
3851da177e4SLinus Torvalds
3861da177e4SLinus Torvalds|
3871da177e4SLinus Torvalds|	mem_write --- write to user or supervisor address space
3881da177e4SLinus Torvalds|
3891da177e4SLinus Torvalds| Writes to memory while in supervisor mode.  copyout accomplishes
3901da177e4SLinus Torvalds| this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
3911da177e4SLinus Torvalds| If you don't have copyout, use the local copy of the function below.
3921da177e4SLinus Torvalds|
3931da177e4SLinus Torvalds|	a0 - supervisor source address
3941da177e4SLinus Torvalds|	a1 - user destination address
3951da177e4SLinus Torvalds|	d0 - number of bytes to write (maximum count is 12)
3961da177e4SLinus Torvalds|
3971da177e4SLinus Torvalds| The supervisor source address is guaranteed to point into the supervisor
3981da177e4SLinus Torvalds| stack.  The result is that a UNIX
3991da177e4SLinus Torvalds| process is allowed to sleep as a consequence of a page fault during
4001da177e4SLinus Torvalds| copyout.  The probability of a page fault is exceedingly small because
4011da177e4SLinus Torvalds| the 68040 always reads the destination address and thus the page
4021da177e4SLinus Torvalds| faults should have already been handled.
4031da177e4SLinus Torvalds|
4041da177e4SLinus Torvalds| If the EXC_SR shows that the exception was from supervisor space,
4051da177e4SLinus Torvalds| then just do a dumb (and slow) memory move.  In a UNIX environment
4061da177e4SLinus Torvalds| there shouldn't be any supervisor mode floating point exceptions.
4071da177e4SLinus Torvalds|
4081da177e4SLinus Torvalds	.global	mem_write
4091da177e4SLinus Torvaldsmem_write:
4101da177e4SLinus Torvalds	btstb	#5,EXC_SR(%a6)	|check for supervisor state
4111da177e4SLinus Torvalds	beqs	user_write
4121da177e4SLinus Torvaldssuper_write:
4131da177e4SLinus Torvalds	moveb	(%a0)+,(%a1)+
4141da177e4SLinus Torvalds	subql	#1,%d0
4151da177e4SLinus Torvalds	bnes	super_write
4161da177e4SLinus Torvalds	rts
4171da177e4SLinus Torvaldsuser_write:
4181da177e4SLinus Torvalds	movel	%d1,-(%sp)	|preserve d1 just in case
4191da177e4SLinus Torvalds	movel	%d0,-(%sp)
4201da177e4SLinus Torvalds	movel	%a1,-(%sp)
4211da177e4SLinus Torvalds	movel	%a0,-(%sp)
4221da177e4SLinus Torvalds	jsr		copyout
4231da177e4SLinus Torvalds	addw	#12,%sp
4241da177e4SLinus Torvalds	movel	(%sp)+,%d1
4251da177e4SLinus Torvalds	rts
4261da177e4SLinus Torvalds|
4271da177e4SLinus Torvalds|	mem_read --- read from user or supervisor address space
4281da177e4SLinus Torvalds|
4291da177e4SLinus Torvalds| Reads from memory while in supervisor mode.  copyin accomplishes
4301da177e4SLinus Torvalds| this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
4311da177e4SLinus Torvalds| If you don't have copyin, use the local copy of the function below.
4321da177e4SLinus Torvalds|
4331da177e4SLinus Torvalds| The FPSP calls mem_read to read the original F-line instruction in order
4341da177e4SLinus Torvalds| to extract the data register number when the 'Dn' addressing mode is
4351da177e4SLinus Torvalds| used.
4361da177e4SLinus Torvalds|
4371da177e4SLinus Torvalds|Input:
4381da177e4SLinus Torvalds|	a0 - user source address
4391da177e4SLinus Torvalds|	a1 - supervisor destination address
4401da177e4SLinus Torvalds|	d0 - number of bytes to read (maximum count is 12)
4411da177e4SLinus Torvalds|
4421da177e4SLinus Torvalds| Like mem_write, mem_read always reads with a supervisor
4431da177e4SLinus Torvalds| destination address on the supervisor stack.  Also like mem_write,
4441da177e4SLinus Torvalds| the EXC_SR is checked and a simple memory copy is done if reading
4451da177e4SLinus Torvalds| from supervisor space is indicated.
4461da177e4SLinus Torvalds|
4471da177e4SLinus Torvalds	.global	mem_read
4481da177e4SLinus Torvaldsmem_read:
4491da177e4SLinus Torvalds	btstb	#5,EXC_SR(%a6)	|check for supervisor state
4501da177e4SLinus Torvalds	beqs	user_read
4511da177e4SLinus Torvaldssuper_read:
4521da177e4SLinus Torvalds	moveb	(%a0)+,(%a1)+
4531da177e4SLinus Torvalds	subql	#1,%d0
4541da177e4SLinus Torvalds	bnes	super_read
4551da177e4SLinus Torvalds	rts
4561da177e4SLinus Torvaldsuser_read:
4571da177e4SLinus Torvalds	movel	%d1,-(%sp)	|preserve d1 just in case
4581da177e4SLinus Torvalds	movel	%d0,-(%sp)
4591da177e4SLinus Torvalds	movel	%a1,-(%sp)
4601da177e4SLinus Torvalds	movel	%a0,-(%sp)
4611da177e4SLinus Torvalds	jsr	copyin
4621da177e4SLinus Torvalds	addw	#12,%sp
4631da177e4SLinus Torvalds	movel	(%sp)+,%d1
4641da177e4SLinus Torvalds	rts
4651da177e4SLinus Torvalds
4661da177e4SLinus Torvalds|
4671da177e4SLinus Torvalds| Use these routines if your kernel doesn't have copyout/copyin equivalents.
4681da177e4SLinus Torvalds| Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
4691da177e4SLinus Torvalds| and copyin overwrites SFC.
4701da177e4SLinus Torvalds|
4711da177e4SLinus Torvaldscopyout:
4721da177e4SLinus Torvalds	movel	4(%sp),%a0	| source
4731da177e4SLinus Torvalds	movel	8(%sp),%a1	| destination
4741da177e4SLinus Torvalds	movel	12(%sp),%d0	| count
4751da177e4SLinus Torvalds	subl	#1,%d0		| dec count by 1 for dbra
4761da177e4SLinus Torvalds	movel	#1,%d1
4771da177e4SLinus Torvalds
4781da177e4SLinus Torvalds|	DFC is already set
4791da177e4SLinus Torvalds|	movec	%d1,%DFC		| set dfc for user data space
4801da177e4SLinus Torvaldsmoreout:
4811da177e4SLinus Torvalds	moveb	(%a0)+,%d1	| fetch supervisor byte
4821da177e4SLinus Torvaldsout_ea:
4831da177e4SLinus Torvalds	movesb	%d1,(%a1)+	| write user byte
4841da177e4SLinus Torvalds	dbf	%d0,moreout
4851da177e4SLinus Torvalds	rts
4861da177e4SLinus Torvalds
4871da177e4SLinus Torvaldscopyin:
4881da177e4SLinus Torvalds	movel	4(%sp),%a0	| source
4891da177e4SLinus Torvalds	movel	8(%sp),%a1	| destination
4901da177e4SLinus Torvalds	movel	12(%sp),%d0	| count
4911da177e4SLinus Torvalds	subl	#1,%d0		| dec count by 1 for dbra
4921da177e4SLinus Torvalds	movel	#1,%d1
4931da177e4SLinus Torvalds|	SFC is already set
4941da177e4SLinus Torvalds|	movec	%d1,%SFC		| set sfc for user space
4951da177e4SLinus Torvaldsmorein:
4961da177e4SLinus Torvaldsin_ea:
4971da177e4SLinus Torvalds	movesb	(%a0)+,%d1	| fetch user byte
4981da177e4SLinus Torvalds	moveb	%d1,(%a1)+	| write supervisor byte
4991da177e4SLinus Torvalds	dbf	%d0,morein
5001da177e4SLinus Torvalds	rts
5011da177e4SLinus Torvalds
502*922a9bd1SBen Hutchings	.section .fixup,"ax"
5031da177e4SLinus Torvalds	.even
5041da177e4SLinus Torvalds1:
505a3616a3cSEric W. Biederman	jbsr	fpsp040_die
506a3616a3cSEric W. Biederman	jbra	.Lnotkern
5071da177e4SLinus Torvalds
508*922a9bd1SBen Hutchings	.section __ex_table,"a"
5091da177e4SLinus Torvalds	.align	4
5101da177e4SLinus Torvalds
5111da177e4SLinus Torvalds	.long	in_ea,1b
5121da177e4SLinus Torvalds	.long	out_ea,1b
5131da177e4SLinus Torvalds
5141da177e4SLinus Torvalds	|end
515