xref: /openbmc/linux/arch/m68k/fpsp040/x_snan.S (revision e00d82d0)
11da177e4SLinus Torvalds|
21da177e4SLinus Torvalds|	x_snan.sa 3.3 7/1/91
31da177e4SLinus Torvalds|
41da177e4SLinus Torvalds| fpsp_snan --- FPSP handler for signalling NAN exception
51da177e4SLinus Torvalds|
61da177e4SLinus Torvalds| SNAN for float -> integer conversions (integer conversion of
71da177e4SLinus Torvalds| an SNAN) is a non-maskable run-time exception.
81da177e4SLinus Torvalds|
91da177e4SLinus Torvalds| For trap disabled the 040 does the following:
101da177e4SLinus Torvalds| If the dest data format is s, d, or x, then the SNAN bit in the NAN
111da177e4SLinus Torvalds| is set to one and the resulting non-signaling NAN (truncated if
121da177e4SLinus Torvalds| necessary) is transferred to the dest.  If the dest format is b, w,
131da177e4SLinus Torvalds| or l, then garbage is written to the dest (actually the upper 32 bits
141da177e4SLinus Torvalds| of the mantissa are sent to the integer unit).
151da177e4SLinus Torvalds|
161da177e4SLinus Torvalds| For trap enabled the 040 does the following:
171da177e4SLinus Torvalds| If the inst is move_out, then the results are the same as for trap
181da177e4SLinus Torvalds| disabled with the exception posted.  If the instruction is not move_
191da177e4SLinus Torvalds| out, the dest. is not modified, and the exception is posted.
201da177e4SLinus Torvalds|
211da177e4SLinus Torvalds
221da177e4SLinus Torvalds|		Copyright (C) Motorola, Inc. 1990
231da177e4SLinus Torvalds|			All Rights Reserved
241da177e4SLinus Torvalds|
25e00d82d0SMatt Waddel|       For details on the license for this file, please see the
26e00d82d0SMatt Waddel|       file, README, in this same directory.
271da177e4SLinus Torvalds
281da177e4SLinus TorvaldsX_SNAN:	|idnt    2,1 | Motorola 040 Floating Point Software Package
291da177e4SLinus Torvalds
301da177e4SLinus Torvalds	|section	8
311da177e4SLinus Torvalds
321da177e4SLinus Torvalds#include "fpsp.h"
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds	|xref	get_fline
351da177e4SLinus Torvalds	|xref	mem_write
361da177e4SLinus Torvalds	|xref	real_snan
371da177e4SLinus Torvalds	|xref	real_inex
381da177e4SLinus Torvalds	|xref	fpsp_done
391da177e4SLinus Torvalds	|xref	reg_dest
401da177e4SLinus Torvalds
411da177e4SLinus Torvalds	.global	fpsp_snan
421da177e4SLinus Torvaldsfpsp_snan:
431da177e4SLinus Torvalds	link		%a6,#-LOCAL_SIZE
441da177e4SLinus Torvalds	fsave		-(%a7)
451da177e4SLinus Torvalds	moveml		%d0-%d1/%a0-%a1,USER_DA(%a6)
461da177e4SLinus Torvalds	fmovemx	%fp0-%fp3,USER_FP0(%a6)
471da177e4SLinus Torvalds	fmoveml	%fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
481da177e4SLinus Torvalds
491da177e4SLinus Torvalds|
501da177e4SLinus Torvalds| Check if trap enabled
511da177e4SLinus Torvalds|
521da177e4SLinus Torvalds	btstb		#snan_bit,FPCR_ENABLE(%a6)
531da177e4SLinus Torvalds	bnes		ena		|If enabled, then branch
541da177e4SLinus Torvalds
551da177e4SLinus Torvalds	bsrl		move_out	|else SNAN disabled
561da177e4SLinus Torvalds|
571da177e4SLinus Torvalds| It is possible to have an inex1 exception with the
581da177e4SLinus Torvalds| snan.  If the inex enable bit is set in the FPCR, and either
591da177e4SLinus Torvalds| inex2 or inex1 occurred, we must clean up and branch to the
601da177e4SLinus Torvalds| real inex handler.
611da177e4SLinus Torvalds|
621da177e4SLinus Torvaldsck_inex:
631da177e4SLinus Torvalds	moveb	FPCR_ENABLE(%a6),%d0
641da177e4SLinus Torvalds	andb	FPSR_EXCEPT(%a6),%d0
651da177e4SLinus Torvalds	andib	#0x3,%d0
661da177e4SLinus Torvalds	beq	end_snan
671da177e4SLinus Torvalds|
681da177e4SLinus Torvalds| Inexact enabled and reported, and we must take an inexact exception.
691da177e4SLinus Torvalds|
701da177e4SLinus Torvaldstake_inex:
711da177e4SLinus Torvalds	moveb		#INEX_VEC,EXC_VEC+1(%a6)
721da177e4SLinus Torvalds	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
731da177e4SLinus Torvalds	fmovemx	USER_FP0(%a6),%fp0-%fp3
741da177e4SLinus Torvalds	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
751da177e4SLinus Torvalds	frestore	(%a7)+
761da177e4SLinus Torvalds	unlk		%a6
771da177e4SLinus Torvalds	bral		real_inex
781da177e4SLinus Torvalds|
791da177e4SLinus Torvalds| SNAN is enabled.  Check if inst is move_out.
801da177e4SLinus Torvalds| Make any corrections to the 040 output as necessary.
811da177e4SLinus Torvalds|
821da177e4SLinus Torvaldsena:
831da177e4SLinus Torvalds	btstb		#5,CMDREG1B(%a6) |if set, inst is move out
841da177e4SLinus Torvalds	beq		not_out
851da177e4SLinus Torvalds
861da177e4SLinus Torvalds	bsrl		move_out
871da177e4SLinus Torvalds
881da177e4SLinus Torvaldsreport_snan:
891da177e4SLinus Torvalds	moveb		(%a7),VER_TMP(%a6)
901da177e4SLinus Torvalds	cmpib		#VER_40,(%a7)	|test for orig unimp frame
911da177e4SLinus Torvalds	bnes		ck_rev
921da177e4SLinus Torvalds	moveql		#13,%d0		|need to zero 14 lwords
931da177e4SLinus Torvalds	bras		rep_con
941da177e4SLinus Torvaldsck_rev:
951da177e4SLinus Torvalds	moveql		#11,%d0		|need to zero 12 lwords
961da177e4SLinus Torvaldsrep_con:
971da177e4SLinus Torvalds	clrl		(%a7)
981da177e4SLinus Torvaldsloop1:
991da177e4SLinus Torvalds	clrl		-(%a7)		|clear and dec a7
1001da177e4SLinus Torvalds	dbra		%d0,loop1
1011da177e4SLinus Torvalds	moveb		VER_TMP(%a6),(%a7) |format a busy frame
1021da177e4SLinus Torvalds	moveb		#BUSY_SIZE-4,1(%a7)
1031da177e4SLinus Torvalds	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
1041da177e4SLinus Torvalds	orl		#sx_mask,E_BYTE(%a6)
1051da177e4SLinus Torvalds	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
1061da177e4SLinus Torvalds	fmovemx	USER_FP0(%a6),%fp0-%fp3
1071da177e4SLinus Torvalds	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
1081da177e4SLinus Torvalds	frestore	(%a7)+
1091da177e4SLinus Torvalds	unlk		%a6
1101da177e4SLinus Torvalds	bral		real_snan
1111da177e4SLinus Torvalds|
1121da177e4SLinus Torvalds| Exit snan handler by expanding the unimp frame into a busy frame
1131da177e4SLinus Torvalds|
1141da177e4SLinus Torvaldsend_snan:
1151da177e4SLinus Torvalds	bclrb		#E1,E_BYTE(%a6)
1161da177e4SLinus Torvalds
1171da177e4SLinus Torvalds	moveb		(%a7),VER_TMP(%a6)
1181da177e4SLinus Torvalds	cmpib		#VER_40,(%a7)	|test for orig unimp frame
1191da177e4SLinus Torvalds	bnes		ck_rev2
1201da177e4SLinus Torvalds	moveql		#13,%d0		|need to zero 14 lwords
1211da177e4SLinus Torvalds	bras		rep_con2
1221da177e4SLinus Torvaldsck_rev2:
1231da177e4SLinus Torvalds	moveql		#11,%d0		|need to zero 12 lwords
1241da177e4SLinus Torvaldsrep_con2:
1251da177e4SLinus Torvalds	clrl		(%a7)
1261da177e4SLinus Torvaldsloop2:
1271da177e4SLinus Torvalds	clrl		-(%a7)		|clear and dec a7
1281da177e4SLinus Torvalds	dbra		%d0,loop2
1291da177e4SLinus Torvalds	moveb		VER_TMP(%a6),(%a7) |format a busy frame
1301da177e4SLinus Torvalds	moveb		#BUSY_SIZE-4,1(%a7) |write busy size
1311da177e4SLinus Torvalds	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
1321da177e4SLinus Torvalds	orl		#sx_mask,E_BYTE(%a6)
1331da177e4SLinus Torvalds	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
1341da177e4SLinus Torvalds	fmovemx	USER_FP0(%a6),%fp0-%fp3
1351da177e4SLinus Torvalds	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
1361da177e4SLinus Torvalds	frestore	(%a7)+
1371da177e4SLinus Torvalds	unlk		%a6
1381da177e4SLinus Torvalds	bral		fpsp_done
1391da177e4SLinus Torvalds
1401da177e4SLinus Torvalds|
1411da177e4SLinus Torvalds| Move_out
1421da177e4SLinus Torvalds|
1431da177e4SLinus Torvaldsmove_out:
1441da177e4SLinus Torvalds	movel		EXC_EA(%a6),%a0	|get <ea> from exc frame
1451da177e4SLinus Torvalds
1461da177e4SLinus Torvalds	bfextu		CMDREG1B(%a6){#3:#3},%d0 |move rx field to d0{2:0}
1471da177e4SLinus Torvalds	cmpil		#0,%d0		|check for long
1481da177e4SLinus Torvalds	beqs		sto_long	|branch if move_out long
1491da177e4SLinus Torvalds
1501da177e4SLinus Torvalds	cmpil		#4,%d0		|check for word
1511da177e4SLinus Torvalds	beqs		sto_word	|branch if move_out word
1521da177e4SLinus Torvalds
1531da177e4SLinus Torvalds	cmpil		#6,%d0		|check for byte
1541da177e4SLinus Torvalds	beqs		sto_byte	|branch if move_out byte
1551da177e4SLinus Torvalds
1561da177e4SLinus Torvalds|
1571da177e4SLinus Torvalds| Not byte, word or long
1581da177e4SLinus Torvalds|
1591da177e4SLinus Torvalds	rts
1601da177e4SLinus Torvalds|
1611da177e4SLinus Torvalds| Get the 32 most significant bits of etemp mantissa
1621da177e4SLinus Torvalds|
1631da177e4SLinus Torvaldssto_long:
1641da177e4SLinus Torvalds	movel		ETEMP_HI(%a6),%d1
1651da177e4SLinus Torvalds	movel		#4,%d0		|load byte count
1661da177e4SLinus Torvalds|
1671da177e4SLinus Torvalds| Set signalling nan bit
1681da177e4SLinus Torvalds|
1691da177e4SLinus Torvalds	bsetl		#30,%d1
1701da177e4SLinus Torvalds|
1711da177e4SLinus Torvalds| Store to the users destination address
1721da177e4SLinus Torvalds|
1731da177e4SLinus Torvalds	tstl		%a0		|check if <ea> is 0
1741da177e4SLinus Torvalds	beqs		wrt_dn		|destination is a data register
1751da177e4SLinus Torvalds
1761da177e4SLinus Torvalds	movel		%d1,-(%a7)	|move the snan onto the stack
1771da177e4SLinus Torvalds	movel		%a0,%a1		|load dest addr into a1
1781da177e4SLinus Torvalds	movel		%a7,%a0		|load src addr of snan into a0
1791da177e4SLinus Torvalds	bsrl		mem_write	|write snan to user memory
1801da177e4SLinus Torvalds	movel		(%a7)+,%d1	|clear off stack
1811da177e4SLinus Torvalds	rts
1821da177e4SLinus Torvalds|
1831da177e4SLinus Torvalds| Get the 16 most significant bits of etemp mantissa
1841da177e4SLinus Torvalds|
1851da177e4SLinus Torvaldssto_word:
1861da177e4SLinus Torvalds	movel		ETEMP_HI(%a6),%d1
1871da177e4SLinus Torvalds	movel		#2,%d0		|load byte count
1881da177e4SLinus Torvalds|
1891da177e4SLinus Torvalds| Set signalling nan bit
1901da177e4SLinus Torvalds|
1911da177e4SLinus Torvalds	bsetl		#30,%d1
1921da177e4SLinus Torvalds|
1931da177e4SLinus Torvalds| Store to the users destination address
1941da177e4SLinus Torvalds|
1951da177e4SLinus Torvalds	tstl		%a0		|check if <ea> is 0
1961da177e4SLinus Torvalds	beqs		wrt_dn		|destination is a data register
1971da177e4SLinus Torvalds
1981da177e4SLinus Torvalds	movel		%d1,-(%a7)	|move the snan onto the stack
1991da177e4SLinus Torvalds	movel		%a0,%a1		|load dest addr into a1
2001da177e4SLinus Torvalds	movel		%a7,%a0		|point to low word
2011da177e4SLinus Torvalds	bsrl		mem_write	|write snan to user memory
2021da177e4SLinus Torvalds	movel		(%a7)+,%d1	|clear off stack
2031da177e4SLinus Torvalds	rts
2041da177e4SLinus Torvalds|
2051da177e4SLinus Torvalds| Get the 8 most significant bits of etemp mantissa
2061da177e4SLinus Torvalds|
2071da177e4SLinus Torvaldssto_byte:
2081da177e4SLinus Torvalds	movel		ETEMP_HI(%a6),%d1
2091da177e4SLinus Torvalds	movel		#1,%d0		|load byte count
2101da177e4SLinus Torvalds|
2111da177e4SLinus Torvalds| Set signalling nan bit
2121da177e4SLinus Torvalds|
2131da177e4SLinus Torvalds	bsetl		#30,%d1
2141da177e4SLinus Torvalds|
2151da177e4SLinus Torvalds| Store to the users destination address
2161da177e4SLinus Torvalds|
2171da177e4SLinus Torvalds	tstl		%a0		|check if <ea> is 0
2181da177e4SLinus Torvalds	beqs		wrt_dn		|destination is a data register
2191da177e4SLinus Torvalds	movel		%d1,-(%a7)	|move the snan onto the stack
2201da177e4SLinus Torvalds	movel		%a0,%a1		|load dest addr into a1
2211da177e4SLinus Torvalds	movel		%a7,%a0		|point to source byte
2221da177e4SLinus Torvalds	bsrl		mem_write	|write snan to user memory
2231da177e4SLinus Torvalds	movel		(%a7)+,%d1	|clear off stack
2241da177e4SLinus Torvalds	rts
2251da177e4SLinus Torvalds
2261da177e4SLinus Torvalds|
2271da177e4SLinus Torvalds|	wrt_dn --- write to a data register
2281da177e4SLinus Torvalds|
2291da177e4SLinus Torvalds|	We get here with D1 containing the data to write and D0 the
2301da177e4SLinus Torvalds|	number of bytes to write: 1=byte,2=word,4=long.
2311da177e4SLinus Torvalds|
2321da177e4SLinus Torvaldswrt_dn:
2331da177e4SLinus Torvalds	movel		%d1,L_SCR1(%a6)	|data
2341da177e4SLinus Torvalds	movel		%d0,-(%a7)	|size
2351da177e4SLinus Torvalds	bsrl		get_fline	|returns fline word in d0
2361da177e4SLinus Torvalds	movel		%d0,%d1
2371da177e4SLinus Torvalds	andil		#0x7,%d1		|d1 now holds register number
2381da177e4SLinus Torvalds	movel		(%sp)+,%d0	|get original size
2391da177e4SLinus Torvalds	cmpil		#4,%d0
2401da177e4SLinus Torvalds	beqs		wrt_long
2411da177e4SLinus Torvalds	cmpil		#2,%d0
2421da177e4SLinus Torvalds	bnes		wrt_byte
2431da177e4SLinus Torvaldswrt_word:
2441da177e4SLinus Torvalds	orl		#0x8,%d1
2451da177e4SLinus Torvalds	bral		reg_dest
2461da177e4SLinus Torvaldswrt_long:
2471da177e4SLinus Torvalds	orl		#0x10,%d1
2481da177e4SLinus Torvalds	bral		reg_dest
2491da177e4SLinus Torvaldswrt_byte:
2501da177e4SLinus Torvalds	bral		reg_dest
2511da177e4SLinus Torvalds|
2521da177e4SLinus Torvalds| Check if it is a src nan or dst nan
2531da177e4SLinus Torvalds|
2541da177e4SLinus Torvaldsnot_out:
2551da177e4SLinus Torvalds	movel		DTAG(%a6),%d0
2561da177e4SLinus Torvalds	bfextu		%d0{#0:#3},%d0	|isolate dtag in lsbs
2571da177e4SLinus Torvalds
2581da177e4SLinus Torvalds	cmpib		#3,%d0		|check for nan in destination
2591da177e4SLinus Torvalds	bnes		issrc		|destination nan has priority
2601da177e4SLinus Torvaldsdst_nan:
2611da177e4SLinus Torvalds	btstb		#6,FPTEMP_HI(%a6) |check if dest nan is an snan
2621da177e4SLinus Torvalds	bnes		issrc		|no, so check source for snan
2631da177e4SLinus Torvalds	movew		FPTEMP_EX(%a6),%d0
2641da177e4SLinus Torvalds	bras		cont
2651da177e4SLinus Torvaldsissrc:
2661da177e4SLinus Torvalds	movew		ETEMP_EX(%a6),%d0
2671da177e4SLinus Torvaldscont:
2681da177e4SLinus Torvalds	btstl		#15,%d0		|test for sign of snan
2691da177e4SLinus Torvalds	beqs		clr_neg
2701da177e4SLinus Torvalds	bsetb		#neg_bit,FPSR_CC(%a6)
2711da177e4SLinus Torvalds	bra		report_snan
2721da177e4SLinus Torvaldsclr_neg:
2731da177e4SLinus Torvalds	bclrb		#neg_bit,FPSR_CC(%a6)
2741da177e4SLinus Torvalds	bra		report_snan
2751da177e4SLinus Torvalds
2761da177e4SLinus Torvalds	|end
277