xref: /netbsd/sys/arch/m68k/fpsp/skeleton.sa (revision bf9ec67e)
1*	$NetBSD: skeleton.sa,v 1.4 2001/09/16 16:34:32 wiz 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*
68sigunimp	dc.l	0
69sigbsun		dc.l	0
70siginex		dc.l	0
71sigdz		dc.l	0
72sigunfl		dc.l	0
73sigovfl		dc.l	0
74sigoperr	dc.l	0
75sigsnan		dc.l	0
76sigunsupp	dc.l	0
77
78	section 8
79
80	include	fpsp.h
81
82	xref	b1238_fix
83
84*
85*	Divide by Zero exception
86*
87*	All dz exceptions are 'real', hence no fpsp_dz entry point.
88*
89	xdef	dz
90	xdef	real_dz
91dz:
92real_dz:
93	link		a6,#-LOCAL_SIZE
94	fsave		-(sp)
95	bclr.b		#E1,E_BYTE(a6)
96	frestore	(sp)+
97	unlk		a6
98
99	add.l	#1,sigdz		;for standalone testing
100
101	rte
102*
103*	Inexact exception
104*
105*	All inexact exceptions are real, but the 'real' handler
106*	will probably want to clear the pending exception.
107*	The provided code will clear the E3 exception (if pending),
108*	otherwise clear the E1 exception.  The frestore is not really
109*	necessary for E1 exceptions.
110*
111* Code following the 'inex' label is to handle bug #1232.  In this
112* bug, if an E1 snan, ovfl, or unfl occurred, and the process was
113* swapped out before taking the exception, the exception taken on
114* return was inex, rather than the correct exception.  The snan, ovfl,
115* and unfl exception to be taken must not have been enabled.  The
116* fix is to check for E1, and the existence of one of snan, ovfl,
117* or unfl bits set in the fpsr.  If any of these are set, branch
118* to the appropriate  handler for the exception in the fpsr.  Note
119* that this fix is only for d43b parts, and is skipped if the
120* version number is not $40.
121*
122*
123	xdef	real_inex
124	xdef	inex
125inex:
126	link		a6,#-LOCAL_SIZE
127	fsave		-(sp)
128	cmpi.b		#VER_40,(sp)		;test version number
129	bne.b		not_fmt40
130	fmove.l		fpsr,-(sp)
131	btst.b		#E1,E_BYTE(a6)		;test for E1 set
132	beq.b		not_b1232
133	btst.b		#snan_bit,2(sp) ;test for snan
134	beq		inex_ckofl
135	add.l		#4,sp
136	frestore	(sp)+
137	unlk		a6
138	bra		snan
139inex_ckofl:
140	btst.b		#ovfl_bit,2(sp) ;test for ovfl
141	beq		inex_ckufl
142	add.l		#4,sp
143	frestore	(sp)+
144	unlk		a6
145	bra		ovfl
146inex_ckufl:
147	btst.b		#unfl_bit,2(sp) ;test for unfl
148	beq		not_b1232
149	add.l		#4,sp
150	frestore	(sp)+
151	unlk		a6
152	bra		unfl
153
154*
155* We do not have the bug 1232 case.  Clean up the stack and call
156* real_inex.
157*
158not_b1232:
159	add.l		#4,sp
160	frestore	(sp)+
161	unlk		a6
162
163real_inex:
164
165	add.l		#1,siginex		;for standalone testing
166
167	link		a6,#-LOCAL_SIZE
168	fsave		-(sp)
169not_fmt40:
170	bclr.b		#E3,E_BYTE(a6)		;clear and test E3 flag
171	beq.b		inex_cke1
172*
173* Clear dirty bit on dest resister in the frame before branching
174* to b1238_fix.
175*
176	movem.l		d0/d1,USER_DA(a6)
177	bfextu		CMDREG1B(a6){6:3},d0		;get dest reg no
178	bclr.b		d0,FPR_DIRTY_BITS(a6)	;clr dest dirty bit
179	bsr.l		b1238_fix		;test for bug1238 case
180	movem.l		USER_DA(a6),d0/d1
181	bra.b		inex_done
182inex_cke1:
183	bclr.b		#E1,E_BYTE(a6)
184inex_done:
185	frestore	(sp)+
186	unlk		a6
187	rte
188
189*
190*	Overflow exception
191*
192	xref	fpsp_ovfl
193	xdef	real_ovfl
194	xdef	ovfl
195ovfl:
196	jmp	fpsp_ovfl
197real_ovfl:
198
199	add.l		#1,sigovfl		;for standalone testing
200
201	link		a6,#-LOCAL_SIZE
202	fsave		-(sp)
203	bclr.b		#E3,E_BYTE(a6)		;clear and test E3 flag
204	bne.b		ovfl_done
205	bclr.b		#E1,E_BYTE(a6)
206ovfl_done:
207	frestore	(sp)+
208	unlk		a6
209	rte
210
211*
212*	Underflow exception
213*
214	xref	fpsp_unfl
215	xdef	real_unfl
216	xdef	unfl
217unfl:
218	jmp	fpsp_unfl
219real_unfl:
220
221	add.l		#1,sigunfl		;for standalone testing
222
223	link		a6,#-LOCAL_SIZE
224	fsave		-(sp)
225	bclr.b		#E3,E_BYTE(a6)		;clear and test E3 flag
226	bne.b		unfl_done
227	bclr.b		#E1,E_BYTE(a6)
228unfl_done:
229	frestore	(sp)+
230	unlk		a6
231	rte
232
233*
234*	Signalling NAN exception
235*
236	xref	fpsp_snan
237	xdef	real_snan
238	xdef	snan
239snan:
240	jmp	fpsp_snan
241real_snan:
242	link		a6,#-LOCAL_SIZE
243	fsave		-(sp)
244	bclr.b		#E1,E_BYTE(a6)	;snan is always an E1 exception
245	frestore	(sp)+
246	unlk		a6
247
248	add.l		#1,sigsnan		;for standalone testing
249	rte
250
251*
252*	Operand Error exception
253*
254	xref	fpsp_operr
255	xdef	real_operr
256	xdef	operr
257operr:
258	jmp	fpsp_operr
259real_operr:
260	link		a6,#-LOCAL_SIZE
261	fsave		-(sp)
262	bclr.b		#E1,E_BYTE(a6)	;operr is always an E1 exception
263	frestore	(sp)+
264	unlk		a6
265
266	add.l		#1,sigoperr		;for standalone testing
267
268	rte
269
270*
271*	BSUN exception
272*
273*	This sample handler simply clears the nan bit in the FPSR.
274*
275	xref	fpsp_bsun
276	xdef	real_bsun
277	xdef	bsun
278bsun:
279	jmp	fpsp_bsun
280real_bsun:
281	link		a6,#-LOCAL_SIZE
282	fsave		-(sp)
283	bclr.b		#E1,E_BYTE(a6)	;bsun is always an E1 exception
284	fmove.l		FPSR,-(sp)
285	bclr.b		#nan_bit,(sp)
286	fmove.l		(sp)+,FPSR
287	frestore	(sp)+
288	unlk		a6
289
290	add.l		#1,sigbsun		;for standalone testing
291
292	rte
293
294*
295*	F-line exception
296*
297*	A 'real' F-line exception is one that the FPSP isn't supposed to
298*	handle. E.g. an instruction with a co-processor ID that is not 1.
299*
300*
301	xref	fpsp_fline
302	xdef	real_fline
303	xdef	fline
304fline:
305	jmp	fpsp_fline
306real_fline:
307
308	add.l		#1,sigunimp		;for standalone testing
309
310	rte
311
312*
313*	Unsupported data type exception
314*
315	xref	fpsp_unsupp
316	xdef	real_unsupp
317	xdef	unsupp
318unsupp:
319	jmp	fpsp_unsupp
320real_unsupp:
321	link		a6,#-LOCAL_SIZE
322	fsave		-(sp)
323	bclr.b		#E1,E_BYTE(a6)	;unsupp is always an E1 exception
324	frestore	(sp)+
325	unlk		a6
326
327	add.l		#1,sigunsupp		;for standalone testing
328
329	rte
330
331*
332*	Trace exception
333*
334	xdef	real_trace
335real_trace:
336	rte
337
338*
339*	fpsp_fmt_error --- exit point for frame format error
340*
341*	The fpu stack frame does not match the frames existing
342*	or planned at the time of this writing.  The fpsp is
343*	unable to handle frame sizes not in the following
344*	version:size pairs:
345*
346*	{4060, 4160} - busy frame
347*	{4028, 4130} - unimp frame
348*	{4000, 4100} - idle frame
349*
350*	This entry point simply holds an f-line illegal value.
351*	Replace this with a call to your kernel panic code or
352*	code to handle future revisions of the fpu.
353*
354	xdef	fpsp_fmt_error
355fpsp_fmt_error:
356
357	dc.l	$f27f0000	;f-line illegal
358
359*
360*	fpsp_done --- FPSP exit point
361*
362*	The exception has been handled by the package and we are ready
363*	to return to user mode, but there may be OS specific code
364*	to execute before we do.  If there is, do it now.
365*
366*
367	xdef	fpsp_done
368fpsp_done:
369	rte
370
371*
372*	mem_write --- write to user or supervisor address space
373*
374* Writes to memory while in supervisor mode.  copyout accomplishes
375* this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
376* If you don't have copyout, use the local copy of the function below.
377*
378*	a0 - supervisor source address
379*	a1 - user destination address
380*	d0 - number of bytes to write (maximum count is 12)
381*
382* The supervisor source address is guaranteed to point into the supervisor
383* stack.  The result is that a UNIX
384* process is allowed to sleep as a consequence of a page fault during
385* copyout.  The probability of a page fault is exceedingly small because
386* the 68040 always reads the destination address and thus the page
387* faults should have already been handled.
388*
389* If the EXC_SR shows that the exception was from supervisor space,
390* then just do a dumb (and slow) memory move.  In a UNIX environment
391* there shouldn't be any supervisor mode floating point exceptions.
392*
393	xdef	mem_write
394mem_write:
395	btst.b	#5,EXC_SR(a6)	;check for supervisor state
396	beq.b	user_write
397super_write:
398	move.b	(a0)+,(a1)+
399	subq.l	#1,d0
400	bne.b	super_write
401	rts
402user_write:
403	move.l	d1,-(sp)	;preserve d1 just in case
404	move.l	d0,-(sp)
405	move.l	a1,-(sp)
406	move.l	a0,-(sp)
407	jsr		copyout
408	add.l	#12,sp
409	move.l	(sp)+,d1
410	rts
411*
412*	mem_read --- read from user or supervisor address space
413*
414* Reads from memory while in supervisor mode.  copyin accomplishes
415* this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
416* If you don't have copyin, use the local copy of the function below.
417*
418* The FPSP calls mem_read to read the original F-line instruction in order
419* to extract the data register number when the 'Dn' addressing mode is
420* used.
421*
422*Input:
423*	a0 - user source address
424*	a1 - supervisor destination address
425*	d0 - number of bytes to read (maximum count is 12)
426*
427* Like mem_write, mem_read always reads with a supervisor
428* destination address on the supervisor stack.  Also like mem_write,
429* the EXC_SR is checked and a simple memory copy is done if reading
430* from supervisor space is indicated.
431*
432	xdef	mem_read
433mem_read:
434	btst.b	#5,EXC_SR(a6)	;check for supervisor state
435	beq.b	user_read
436super_read:
437	move.b	(a0)+,(a1)+
438	subq.l	#1,d0
439	bne.b	super_read
440	rts
441user_read:
442	move.l	d1,-(sp)	;preserve d1 just in case
443	move.l	d0,-(sp)
444	move.l	a1,-(sp)
445	move.l	a0,-(sp)
446	jsr		copyin
447	add.l	#12,sp
448	move.l	(sp)+,d1
449	rts
450
451*
452* Use these routines if your kernel doesn't have copyout/copyin equivalents.
453* Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
454* and copyin overwrites SFC.
455*
456copyout:
457	move.l	4(sp),a0	; source
458	move.l	8(sp),a1	; destination
459	move.l	12(sp),d0	; count
460	sub.l	#1,d0		; dec count by 1 for dbra
461	move.l	#1,d1
462	movec	d1,DFC		; set dfc for user data space
463moreout:
464	move.b	(a0)+,d1	; fetch supervisor byte
465	moves.b	d1,(a1)+	; write user byte
466	dbf.w	d0,moreout
467	rts
468
469copyin:
470	move.l	4(sp),a0	; source
471	move.l	8(sp),a1	; destination
472	move.l	12(sp),d0	; count
473	sub.l	#1,d0		; dec count by 1 for dbra
474	move.l	#1,d1
475	movec	d1,SFC		; set sfc for user space
476morein:
477	moves.b	(a0)+,d1	; fetch user byte
478	move.b	d1,(a1)+	; write supervisor byte
479	dbf.w	d0,morein
480	rts
481
482	end
483