Home | History | Annotate | Line # | Download | only in fpsp
      1 *	$NetBSD: netbsd.sa,v 1.6 2024/09/20 19:38:53 andvar 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 
     62 SKELETON	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
     88 dz:
     89 	cmp.l		#-2,_C_LABEL(mmutype)
     90 	bne.l		_C_LABEL(fpfault)
     91 real_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
    122 inex:
    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
    138 inex_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
    145 inex_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 *
    157 not_b1232:
    158 	addq.l		#4,sp
    159 	frestore	(sp)+
    160 	unlk		a6
    161 
    162 real_inex:
    163 	link		a6,#-LOCAL_SIZE
    164 	fsave		-(sp)
    165 not_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 register 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
    178 inex_cke1:
    179 	bclr.b		#E1,E_BYTE(a6)
    180 inex_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
    191 ovfl:
    192 	cmp.l		#-2,_C_LABEL(mmutype)
    193 	beq.l		fpsp_ovfl
    194 	jmp		_C_LABEL(fpfault)
    195 real_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)
    201 ovfl_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
    212 unfl:
    213 	cmp.l		#-2,_C_LABEL(mmutype)
    214 	beq.l		fpsp_unfl
    215 	jmp		_C_LABEL(fpfault)
    216 real_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)
    222 unfl_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
    233 snan:
    234 	cmp.l		#-2,_C_LABEL(mmutype)
    235 	beq.l		fpsp_snan
    236 	jmp		_C_LABEL(fpfault)
    237 real_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
    251 operr:
    252 	cmp.l		#-2,_C_LABEL(mmutype)
    253 	beq.l		fpsp_operr
    254 	jmp		_C_LABEL(fpfault)
    255 real_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
    271 bsun:
    272 	cmp.l		#-2,_C_LABEL(mmutype)
    273 	beq.l		fpsp_bsun
    274 	jmp		_C_LABEL(fpfault)
    275 real_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
    296 fline:
    297 	cmp.l		#-2,_C_LABEL(mmutype)
    298 	beq.l		fpsp_fline
    299 	jmp		_C_LABEL(fpfault)
    300 real_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
    309 unsupp:
    310 	cmp.l		#-2,_C_LABEL(mmutype)
    311 	beq.l		fpsp_unsupp
    312 	jmp		_C_LABEL(fpfault)
    313 real_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
    325 real_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
    345 fpsp_fmt_error:
    346 	pea		1f
    347 	jsr		_C_LABEL(panic)
    348 	dc.l		$f27f0000	;f-line illegal
    349 1:
    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
    363 fpsp_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
    389 mem_write:
    390 	btst.b	#5,EXC_SR(a6)	;check for supervisor state
    391 	beq.b	user_write
    392 super_write:
    393 	move.b	(a0)+,(a1)+
    394 	subq.l	#1,d0
    395 	bne.b	super_write
    396 	rts
    397 user_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
    429 mem_read:
    430 	btst.b	#5,EXC_SR(a6)	;check for supervisor state
    431 	beq.b	user_read
    432 super_read:
    433 	move.b	(a0)+,(a1)+
    434 	subq.l	#1,d0
    435 	bne.b	super_read
    436 	rts
    437 user_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