Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

*	$NetBSD: x_snan.sa,v 1.4 2001/09/16 16:34:32 wiz Exp $

*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
*	M68000 Hi-Performance Microprocessor Division
*	M68040 Software Package 
*
*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
*	All rights reserved.
*
*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
*	To the maximum extent permitted by applicable law,
*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
*	PARTICULAR PURPOSE and any warranty against infringement with
*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
*	and any accompanying written materials. 
*
*	To the maximum extent permitted by applicable law,
*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
*	and support of the SOFTWARE.  
*
*	You are hereby granted a copyright license to use, modify, and
*	distribute the SOFTWARE so long as this entire notice is retained
*	without alteration in any modified and/or redistributed versions,
*	and that such modified versions are clearly identified as such.
*	No licenses are granted by implication, estoppel or otherwise
*	under any patents or trademarks of Motorola, Inc.

*
*	x_snan.sa 3.3 7/1/91
*
* fpsp_snan --- FPSP handler for signalling NAN exception
*
* SNAN for float -> integer conversions (integer conversion of
* an SNAN) is a non-maskable run-time exception.
*
* For trap disabled the 040 does the following:
* If the dest data format is s, d, or x, then the SNAN bit in the NAN
* is set to one and the resulting non-signaling NAN (truncated if
* necessary) is transferred to the dest.  If the dest format is b, w,
* or l, then garbage is written to the dest (actually the upper 32 bits
* of the mantissa are sent to the integer unit).
*
* For trap enabled the 040 does the following:
* If the inst is move_out, then the results are the same as for trap 
* disabled with the exception posted.  If the instruction is not move_
* out, the dest. is not modified, and the exception is posted.
*

X_SNAN	IDNT    2,1 Motorola 040 Floating Point Software Package

	section	8

	include	fpsp.h

	xref	get_fline
	xref	mem_write
	xref	real_snan
	xref	real_inex
	xref	fpsp_done
	xref	reg_dest

	xdef	fpsp_snan
fpsp_snan:
	link		a6,#-LOCAL_SIZE
	fsave		-(a7)
	movem.l		d0-d1/a0-a1,USER_DA(a6)
	fmovem.x	fp0-fp3,USER_FP0(a6)
	fmovem.l	fpcr/fpsr/fpiar,USER_FPCR(a6)

*
* Check if trap enabled
*
	btst.b		#snan_bit,FPCR_ENABLE(a6)
	bne.b		ena		;If enabled, then branch

	bsr.l		move_out	;else SNAN disabled
*
* It is possible to have an inex1 exception with the
* snan.  If the inex enable bit is set in the FPCR, and either
* inex2 or inex1 occurred, we must clean up and branch to the
* real inex handler.
*
ck_inex:
	move.b	FPCR_ENABLE(a6),d0
	and.b	FPSR_EXCEPT(a6),d0
	andi.b	#$3,d0
	beq.w	end_snan
*
* Inexact enabled and reported, and we must take an inexact exception.
*
take_inex:
	move.b		#INEX_VEC,EXC_VEC+1(a6)
	movem.l		USER_DA(a6),d0-d1/a0-a1
	fmovem.x	USER_FP0(a6),fp0-fp3
	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
	frestore	(a7)+
	unlk		a6
	bra.l		real_inex
*
* SNAN is enabled.  Check if inst is move_out.
* Make any corrections to the 040 output as necessary.
*
ena:
	btst.b		#5,CMDREG1B(a6) ;if set, inst is move out
	beq.w		not_out

	bsr.l		move_out

report_snan:
	move.b		(a7),VER_TMP(a6)
	cmpi.b		#VER_40,(a7)	;test for orig unimp frame
	bne.b		ck_rev
	moveq.l		#13,d0		;need to zero 14 lwords
	bra.b		rep_con
ck_rev:
	moveq.l		#11,d0		;need to zero 12 lwords
rep_con:
	clr.l		(a7)
loop1:
	clr.l		-(a7)		;clear and dec a7
	dbra.w		d0,loop1
	move.b		VER_TMP(a6),(a7) ;format a busy frame
	move.b		#BUSY_SIZE-4,1(a7)
	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
	or.l		#sx_mask,E_BYTE(a6)
	movem.l		USER_DA(a6),d0-d1/a0-a1
	fmovem.x	USER_FP0(a6),fp0-fp3
	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
	frestore	(a7)+
	unlk		a6
	bra.l		real_snan
*
* Exit snan handler by expanding the unimp frame into a busy frame
*
end_snan:
	bclr.b		#E1,E_BYTE(a6)

	move.b		(a7),VER_TMP(a6)
	cmpi.b		#VER_40,(a7)	;test for orig unimp frame
	bne.b		ck_rev2
	moveq.l		#13,d0		;need to zero 14 lwords
	bra.b		rep_con2
ck_rev2:
	moveq.l		#11,d0		;need to zero 12 lwords
rep_con2:
	clr.l		(a7)
loop2:
	clr.l		-(a7)		;clear and dec a7
	dbra.w		d0,loop2
	move.b		VER_TMP(a6),(a7) ;format a busy frame
	move.b		#BUSY_SIZE-4,1(a7) ;write busy size
	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
	or.l		#sx_mask,E_BYTE(a6)
	movem.l		USER_DA(a6),d0-d1/a0-a1
	fmovem.x	USER_FP0(a6),fp0-fp3
	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
	frestore	(a7)+
	unlk		a6
	bra.l		fpsp_done

*
* Move_out 
*
move_out:
	move.l		EXC_EA(a6),a0	;get <ea> from exc frame

	bfextu		CMDREG1B(a6){3:3},d0 ;move rx field to d0{2:0}
	tst.l		d0		;check for long
	beq.b		sto_long	;branch if move_out long
	
	cmpi.l		#4,d0		;check for word
	beq.b		sto_word	;branch if move_out word
	
	cmpi.l		#6,d0		;check for byte
	beq.b		sto_byte	;branch if move_out byte
	
*
* Not byte, word or long
*
	rts
*	
* Get the 32 most significant bits of etemp mantissa
*
sto_long:
	move.l		ETEMP_HI(a6),d1
	move.l		#4,d0		;load byte count
*
* Set signalling nan bit
*
	bset.l		#30,d1			
*
* Store to the users destination address
*
	tst.l		a0		;check if <ea> is 0
	beq.b		wrt_dn		;destination is a data register
	
	move.l		d1,-(a7)	;move the snan onto the stack
	move.l		a0,a1		;load dest addr into a1
	move.l		a7,a0		;load src addr of snan into a0
	bsr.l		mem_write	;write snan to user memory
	move.l		(a7)+,d1	;clear off stack
	rts
*
* Get the 16 most significant bits of etemp mantissa
*
sto_word:
	move.l		ETEMP_HI(a6),d1
	move.l		#2,d0		;load byte count
*
* Set signalling nan bit
*
	bset.l		#30,d1			
*
* Store to the users destination address
*
	tst.l		a0		;check if <ea> is 0
	beq.b		wrt_dn		;destination is a data register

	move.l		d1,-(a7)	;move the snan onto the stack
	move.l		a0,a1		;load dest addr into a1
	move.l		a7,a0		;point to low word
	bsr.l		mem_write	;write snan to user memory
	move.l		(a7)+,d1	;clear off stack
	rts
*
* Get the 8 most significant bits of etemp mantissa
*
sto_byte:
	move.l		ETEMP_HI(a6),d1
	move.l		#1,d0		;load byte count
*
* Set signalling nan bit
*
	bset.l		#30,d1			
*
* Store to the users destination address
*
	tst.l		a0		;check if <ea> is 0
	beq.b		wrt_dn		;destination is a data register
	move.l		d1,-(a7)	;move the snan onto the stack
	move.l		a0,a1		;load dest addr into a1
	move.l		a7,a0		;point to source byte
	bsr.l		mem_write	;write snan to user memory
	move.l		(a7)+,d1	;clear off stack
	rts

*
*	wrt_dn --- write to a data register
*
*	We get here with D1 containing the data to write and D0 the
*	number of bytes to write: 1=byte,2=word,4=long.
*
wrt_dn:
	move.l		d1,L_SCR1(a6)	;data
	move.l		d0,-(a7)	;size
	bsr.l		get_fline	;returns fline word in d0
	move.l		d0,d1
	andi.l		#$7,d1		;d1 now holds register number
	move.l		(sp)+,d0	;get original size
	cmpi.l		#4,d0
	beq.b		wrt_long
	cmpi.l		#2,d0
	bne.b		wrt_byte
wrt_word:
	or.l		#$8,d1
	bra.l		reg_dest
wrt_long:
	or.l		#$10,d1
	bra.l		reg_dest
wrt_byte:
	bra.l		reg_dest
*
* Check if it is a src nan or dst nan
*
not_out:
	move.l		DTAG(a6),d0	
	bfextu		d0{0:3},d0	;isolate dtag in lsbs

	cmpi.b		#3,d0		;check for nan in destination
	bne.b		issrc		;destination nan has priority
dst_nan:
	btst.b		#6,FPTEMP_HI(a6) ;check if dest nan is an snan
	bne.b		issrc		;no, so check source for snan
	move.w		FPTEMP_EX(a6),d0
	bra.b		cont
issrc:
	move.w		ETEMP_EX(a6),d0
cont:
	btst.l		#15,d0		;test for sign of snan
	beq.b		clr_neg
	bset.b		#neg_bit,FPSR_CC(a6)
	bra.w		report_snan
clr_neg:
	bclr.b		#neg_bit,FPSR_CC(a6)
	bra.w		report_snan

	end