xref: /netbsd/sys/arch/m68k/fpsp/netbsd.sa (revision bf9ec67e)
1*	$NetBSD: netbsd.sa,v 1.5 2001/10/02 06:34:52 chs Exp $
2
3*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
4*	M68000 Hi-Performance Microprocessor Division
5*	M68040 Software Package
6*
7*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
8*	All rights reserved.
9*
10*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
11*	To the maximum extent permitted by applicable law,
12*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
13*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
14*	PARTICULAR PURPOSE and any warranty against infringement with
15*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
16*	and any accompanying written materials.
17*
18*	To the maximum extent permitted by applicable law,
19*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
20*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
21*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
22*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
23*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
24*	and support of the SOFTWARE.
25*
26*	You are hereby granted a copyright license to use, modify, and
27*	distribute the SOFTWARE so long as this entire notice is retained
28*	without alteration in any modified and/or redistributed versions,
29*	and that such modified versions are clearly identified as such.
30*	No licenses are granted by implication, estoppel or otherwise
31*	under any patents or trademarks of Motorola, Inc.
32
33*
34*	skeleton.sa 3.2 4/26/91
35*
36*	This file contains code that is system dependent and will
37*	need to be modified to install the FPSP.
38*
39*	Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
40*	Put any target system specific handling that must be done immediately
41*	before the jump instruction.  If there no handling necessary, then
42*	the 'fpsp_xxxx' handler entry point should be placed in the exception
43*	table so that the 'jmp' can be eliminated. If the FPSP determines that the
44*	exception is one that must be reported then there will be a
45*	return from the package by a 'jmp real_xxxx'.  At that point
46*	the machine state will be identical to the state before
47*	the FPSP was entered.  In particular, whatever condition
48*	that caused the exception will still be pending when the FPSP
49*	package returns.  Thus, there will be system specific code
50*	to handle the exception.
51*
52*	If the exception was completely handled by the package, then
53*	the return will be via a 'jmp fpsp_done'.  Unless there is
54*	OS specific work to be done (such as handling a context switch or
55*	interrupt) the user program can be resumed via 'rte'.
56*
57*	In the following skeleton code, some typical 'real_xxxx' handling
58*	code is shown.  This code may need to be moved to an appropriate
59*	place in the target system, or rewritten.
60*
61
62SKELETON	IDNT    2,1 Motorola 040 Floating Point Software Package
63
64	section 15
65*
66*	The following counters are used for standalone testing
67*
68
69	section 8
70
71	include	fpsp.h
72
73*
74* XXX Note, this is NOT valid Motorola syntax, but what else can we do?
75*
76#include <machine/asm.h>
77
78	xref	b1238_fix
79	xref	_C_LABEL(mmutype)
80
81*
82*	Divide by Zero exception
83*
84*	All dz exceptions are 'real', hence no fpsp_dz entry point.
85*
86	xdef	dz
87	xdef	real_dz
88dz:
89	cmp.l		#-2,_C_LABEL(mmutype)
90	bne.l		_C_LABEL(fpfault)
91real_dz:
92	link		a6,#-LOCAL_SIZE
93	fsave		-(sp)
94	bclr.b		#E1,E_BYTE(a6)
95	frestore	(sp)+
96	unlk		a6
97	jmp		_C_LABEL(fpfault)
98
99*
100*	Inexact exception
101*
102*	All inexact exceptions are real, but the 'real' handler
103*	will probably want to clear the pending exception.
104*	The provided code will clear the E3 exception (if pending),
105*	otherwise clear the E1 exception.  The frestore is not really
106*	necessary for E1 exceptions.
107*
108* Code following the 'inex' label is to handle bug #1232.  In this
109* bug, if an E1 snan, ovfl, or unfl occurred, and the process was
110* swapped out before taking the exception, the exception taken on
111* return was inex, rather than the correct exception.  The snan, ovfl,
112* and unfl exception to be taken must not have been enabled.  The
113* fix is to check for E1, and the existence of one of snan, ovfl,
114* or unfl bits set in the fpsr.  If any of these are set, branch
115* to the appropriate  handler for the exception in the fpsr.  Note
116* that this fix is only for d43b parts, and is skipped if the
117* version number is not $40.
118*
119*
120	xdef	real_inex
121	xdef	inex
122inex:
123	cmp.l		#-2,_C_LABEL(mmutype)
124	bne.l		_C_LABEL(fpfault)
125	link		a6,#-LOCAL_SIZE
126	fsave		-(sp)
127	cmpi.b		#VER_40,(sp)		;test version number
128	bne.b		not_fmt40
129	fmove.l		fpsr,-(sp)
130	btst.b		#E1,E_BYTE(a6)		;test for E1 set
131	beq.b		not_b1232
132	btst.b		#snan_bit,2(sp) ;test for snan
133	beq		inex_ckofl
134	addq.l		#4,sp
135	frestore	(sp)+
136	unlk		a6
137	bra		snan
138inex_ckofl:
139	btst.b		#ovfl_bit,2(sp) ;test for ovfl
140	beq		inex_ckufl
141	addq.l		#4,sp
142	frestore	(sp)+
143	unlk		a6
144	bra		ovfl
145inex_ckufl:
146	btst.b		#unfl_bit,2(sp) ;test for unfl
147	beq		not_b1232
148	addq.l		#4,sp
149	frestore	(sp)+
150	unlk		a6
151	bra		unfl
152
153*
154* We do not have the bug 1232 case.  Clean up the stack and call
155* real_inex.
156*
157not_b1232:
158	addq.l		#4,sp
159	frestore	(sp)+
160	unlk		a6
161
162real_inex:
163	link		a6,#-LOCAL_SIZE
164	fsave		-(sp)
165not_fmt40:
166	bclr.b		#E3,E_BYTE(a6)		;clear and test E3 flag
167	beq.b		inex_cke1
168*
169* Clear dirty bit on dest resister in the frame before branching
170* to b1238_fix.
171*
172	movem.l		d0/d1,USER_DA(a6)
173	bfextu		CMDREG1B(a6){6:3},d0		;get dest reg no
174	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
175	bsr.l		b1238_fix		;test for bug1238 case
176	movem.l		USER_DA(a6),d0/d1
177	bra.b		inex_done
178inex_cke1:
179	bclr.b		#E1,E_BYTE(a6)
180inex_done:
181	frestore	(sp)+
182	unlk		a6
183	jmp		_C_LABEL(fpfault)
184
185*
186*	Overflow exception
187*
188	xref	fpsp_ovfl
189	xdef	real_ovfl
190	xdef	ovfl
191ovfl:
192	cmp.l		#-2,_C_LABEL(mmutype)
193	beq.l		fpsp_ovfl
194	jmp		_C_LABEL(fpfault)
195real_ovfl:
196	link		a6,#-LOCAL_SIZE
197	fsave		-(sp)
198	bclr.b		#E3,E_BYTE(a6)		;clear and test E3 flag
199	bne.b		ovfl_done
200	bclr.b		#E1,E_BYTE(a6)
201ovfl_done:
202	frestore	(sp)+
203	unlk		a6
204	jmp		_C_LABEL(fpfault)
205
206*
207*	Underflow exception
208*
209	xref	fpsp_unfl
210	xdef	real_unfl
211	xdef	unfl
212unfl:
213	cmp.l		#-2,_C_LABEL(mmutype)
214	beq.l		fpsp_unfl
215	jmp		_C_LABEL(fpfault)
216real_unfl:
217	link		a6,#-LOCAL_SIZE
218	fsave		-(sp)
219	bclr.b		#E3,E_BYTE(a6)		;clear and test E3 flag
220	bne.b		unfl_done
221	bclr.b		#E1,E_BYTE(a6)
222unfl_done:
223	frestore	(sp)+
224	unlk		a6
225	jmp		_C_LABEL(fpfault)
226
227*
228*	Signalling NAN exception
229*
230	xref	fpsp_snan
231	xdef	real_snan
232	xdef	snan
233snan:
234	cmp.l		#-2,_C_LABEL(mmutype)
235	beq.l		fpsp_snan
236	jmp		_C_LABEL(fpfault)
237real_snan:
238	link		a6,#-LOCAL_SIZE
239	fsave		-(sp)
240	bclr.b		#E1,E_BYTE(a6)	;snan is always an E1 exception
241	frestore	(sp)+
242	unlk		a6
243	jmp		_C_LABEL(fpfault)
244
245*
246*	Operand Error exception
247*
248	xref	fpsp_operr
249	xdef	real_operr
250	xdef	operr
251operr:
252	cmp.l		#-2,_C_LABEL(mmutype)
253	beq.l		fpsp_operr
254	jmp		_C_LABEL(fpfault)
255real_operr:
256	link		a6,#-LOCAL_SIZE
257	fsave		-(sp)
258	bclr.b		#E1,E_BYTE(a6)	;operr is always an E1 exception
259	frestore	(sp)+
260	unlk		a6
261	jmp		_C_LABEL(fpfault)
262
263*
264*	BSUN exception
265*
266*	This sample handler simply clears the nan bit in the FPSR.
267*
268	xref	fpsp_bsun
269	xdef	real_bsun
270	xdef	bsun
271bsun:
272	cmp.l		#-2,_C_LABEL(mmutype)
273	beq.l		fpsp_bsun
274	jmp		_C_LABEL(fpfault)
275real_bsun:
276	link		a6,#-LOCAL_SIZE
277	fsave		-(sp)
278	bclr.b		#E1,E_BYTE(a6)	;bsun is always an E1 exception
279	fmove.l		FPSR,-(sp)
280	bclr.b		#nan_bit,(sp)
281	fmove.l		(sp)+,FPSR
282	frestore	(sp)+
283	unlk		a6
284	jmp		_C_LABEL(fpfault)
285
286*
287*	F-line exception
288*
289*	A 'real' F-line exception is one that the FPSP isn't supposed to
290*	handle. E.g. an instruction with a co-processor ID that is not 1.
291*
292*
293	xref	fpsp_fline
294	xdef	real_fline
295	xdef	fline
296fline:
297	cmp.l		#-2,_C_LABEL(mmutype)
298	beq.l		fpsp_fline
299	jmp		_C_LABEL(fpfault)
300real_fline:
301	jmp		_C_LABEL(fpfault)
302
303*
304*	Unsupported data type exception
305*
306	xref	fpsp_unsupp
307	xdef	real_unsupp
308	xdef	unsupp
309unsupp:
310	cmp.l		#-2,_C_LABEL(mmutype)
311	beq.l		fpsp_unsupp
312	jmp		_C_LABEL(fpfault)
313real_unsupp:
314	link		a6,#-LOCAL_SIZE
315	fsave		-(sp)
316	bclr.b		#E1,E_BYTE(a6)	;unsupp is always an E1 exception
317	frestore	(sp)+
318	unlk		a6
319	jmp		_C_LABEL(fpfault)
320
321*
322*	Trace exception
323*
324	xdef	real_trace
325real_trace:
326	rte
327
328*
329*	fpsp_fmt_error --- exit point for frame format error
330*
331*	The fpu stack frame does not match the frames existing
332*	or planned at the time of this writing.  The fpsp is
333*	unable to handle frame sizes not in the following
334*	version:size pairs:
335*
336*	{4060, 4160} - busy frame
337*	{4028, 4130} - unimp frame
338*	{4000, 4100} - idle frame
339*
340*	This entry point simply holds an f-line illegal value.
341*	Replace this with a call to your kernel panic code or
342*	code to handle future revisions of the fpu.
343*
344	xdef	fpsp_fmt_error
345fpsp_fmt_error:
346	pea		1f
347	jsr		_C_LABEL(panic)
348	dc.l		$f27f0000	;f-line illegal
3491:
350	.asciz		"bad floating point stack frame"
351	.even
352
353*
354*	fpsp_done --- FPSP exit point
355*
356*	The exception has been handled by the package and we are ready
357*	to return to user mode, but there may be OS specific code
358*	to execute before we do.  If there is, do it now.
359*
360*
361	xref	_ASM_LABEL(rei)
362	xdef	fpsp_done
363fpsp_done:
364	jmp		_ASM_LABEL(rei)
365
366*
367*	mem_write --- write to user or supervisor address space
368*
369* Writes to memory while in supervisor mode.  copyout accomplishes
370* this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
371* If you don't have copyout, use the local copy of the function below.
372*
373*	a0 - supervisor source address
374*	a1 - user destination address
375*	d0 - number of bytes to write (maximum count is 12)
376*
377* The supervisor source address is guaranteed to point into the supervisor
378* stack.  The result is that a UNIX
379* process is allowed to sleep as a consequence of a page fault during
380* copyout.  The probability of a page fault is exceedingly small because
381* the 68040 always reads the destination address and thus the page
382* faults should have already been handled.
383*
384* If the EXC_SR shows that the exception was from supervisor space,
385* then just do a dumb (and slow) memory move.  In a UNIX environment
386* there shouldn't be any supervisor mode floating point exceptions.
387*
388	xdef	mem_write
389mem_write:
390	btst.b	#5,EXC_SR(a6)	;check for supervisor state
391	beq.b	user_write
392super_write:
393	move.b	(a0)+,(a1)+
394	subq.l	#1,d0
395	bne.b	super_write
396	rts
397user_write:
398	move.l	d1,-(sp)	;preserve d1 just in case
399	move.l	d0,-(sp)
400	move.l	a1,-(sp)
401	move.l	a0,-(sp)
402	jsr	_C_LABEL(copyout)
403	add.l	#12,sp
404	move.l	(sp)+,d1
405	rts
406
407*
408*	mem_read --- read from user or supervisor address space
409*
410* Reads from memory while in supervisor mode.  copyin accomplishes
411* this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
412* If you don't have copyin, use the local copy of the function below.
413*
414* The FPSP calls mem_read to read the original F-line instruction in order
415* to extract the data register number when the 'Dn' addressing mode is
416* used.
417*
418*Input:
419*	a0 - user source address
420*	a1 - supervisor destination address
421*	d0 - number of bytes to read (maximum count is 12)
422*
423* Like mem_write, mem_read always reads with a supervisor
424* destination address on the supervisor stack.  Also like mem_write,
425* the EXC_SR is checked and a simple memory copy is done if reading
426* from supervisor space is indicated.
427*
428	xdef	mem_read
429mem_read:
430	btst.b	#5,EXC_SR(a6)	;check for supervisor state
431	beq.b	user_read
432super_read:
433	move.b	(a0)+,(a1)+
434	subq.l	#1,d0
435	bne.b	super_read
436	rts
437user_read:
438	move.l	d1,-(sp)	;preserve d1 just in case
439	move.l	d0,-(sp)
440	move.l	a1,-(sp)
441	move.l	a0,-(sp)
442	jsr	_C_LABEL(copyin)
443	add.l	#12,sp
444	move.l	(sp)+,d1
445	rts
446
447	end
448