162306a36Sopenharmony_ci|
262306a36Sopenharmony_ci|	x_snan.sa 3.3 7/1/91
362306a36Sopenharmony_ci|
462306a36Sopenharmony_ci| fpsp_snan --- FPSP handler for signalling NAN exception
562306a36Sopenharmony_ci|
662306a36Sopenharmony_ci| SNAN for float -> integer conversions (integer conversion of
762306a36Sopenharmony_ci| an SNAN) is a non-maskable run-time exception.
862306a36Sopenharmony_ci|
962306a36Sopenharmony_ci| For trap disabled the 040 does the following:
1062306a36Sopenharmony_ci| If the dest data format is s, d, or x, then the SNAN bit in the NAN
1162306a36Sopenharmony_ci| is set to one and the resulting non-signaling NAN (truncated if
1262306a36Sopenharmony_ci| necessary) is transferred to the dest.  If the dest format is b, w,
1362306a36Sopenharmony_ci| or l, then garbage is written to the dest (actually the upper 32 bits
1462306a36Sopenharmony_ci| of the mantissa are sent to the integer unit).
1562306a36Sopenharmony_ci|
1662306a36Sopenharmony_ci| For trap enabled the 040 does the following:
1762306a36Sopenharmony_ci| If the inst is move_out, then the results are the same as for trap
1862306a36Sopenharmony_ci| disabled with the exception posted.  If the instruction is not move_
1962306a36Sopenharmony_ci| out, the dest. is not modified, and the exception is posted.
2062306a36Sopenharmony_ci|
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
2362306a36Sopenharmony_ci|			All Rights Reserved
2462306a36Sopenharmony_ci|
2562306a36Sopenharmony_ci|       For details on the license for this file, please see the
2662306a36Sopenharmony_ci|       file, README, in this same directory.
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ciX_SNAN:	|idnt    2,1 | Motorola 040 Floating Point Software Package
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	|section	8
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include "fpsp.h"
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	|xref	get_fline
3562306a36Sopenharmony_ci	|xref	mem_write
3662306a36Sopenharmony_ci	|xref	real_snan
3762306a36Sopenharmony_ci	|xref	real_inex
3862306a36Sopenharmony_ci	|xref	fpsp_done
3962306a36Sopenharmony_ci	|xref	reg_dest
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	.global	fpsp_snan
4262306a36Sopenharmony_cifpsp_snan:
4362306a36Sopenharmony_ci	link		%a6,#-LOCAL_SIZE
4462306a36Sopenharmony_ci	fsave		-(%a7)
4562306a36Sopenharmony_ci	moveml		%d0-%d1/%a0-%a1,USER_DA(%a6)
4662306a36Sopenharmony_ci	fmovemx	%fp0-%fp3,USER_FP0(%a6)
4762306a36Sopenharmony_ci	fmoveml	%fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci|
5062306a36Sopenharmony_ci| Check if trap enabled
5162306a36Sopenharmony_ci|
5262306a36Sopenharmony_ci	btstb		#snan_bit,FPCR_ENABLE(%a6)
5362306a36Sopenharmony_ci	bnes		ena		|If enabled, then branch
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	bsrl		move_out	|else SNAN disabled
5662306a36Sopenharmony_ci|
5762306a36Sopenharmony_ci| It is possible to have an inex1 exception with the
5862306a36Sopenharmony_ci| snan.  If the inex enable bit is set in the FPCR, and either
5962306a36Sopenharmony_ci| inex2 or inex1 occurred, we must clean up and branch to the
6062306a36Sopenharmony_ci| real inex handler.
6162306a36Sopenharmony_ci|
6262306a36Sopenharmony_cick_inex:
6362306a36Sopenharmony_ci	moveb	FPCR_ENABLE(%a6),%d0
6462306a36Sopenharmony_ci	andb	FPSR_EXCEPT(%a6),%d0
6562306a36Sopenharmony_ci	andib	#0x3,%d0
6662306a36Sopenharmony_ci	beq	end_snan
6762306a36Sopenharmony_ci|
6862306a36Sopenharmony_ci| Inexact enabled and reported, and we must take an inexact exception.
6962306a36Sopenharmony_ci|
7062306a36Sopenharmony_citake_inex:
7162306a36Sopenharmony_ci	moveb		#INEX_VEC,EXC_VEC+1(%a6)
7262306a36Sopenharmony_ci	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
7362306a36Sopenharmony_ci	fmovemx	USER_FP0(%a6),%fp0-%fp3
7462306a36Sopenharmony_ci	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
7562306a36Sopenharmony_ci	frestore	(%a7)+
7662306a36Sopenharmony_ci	unlk		%a6
7762306a36Sopenharmony_ci	bral		real_inex
7862306a36Sopenharmony_ci|
7962306a36Sopenharmony_ci| SNAN is enabled.  Check if inst is move_out.
8062306a36Sopenharmony_ci| Make any corrections to the 040 output as necessary.
8162306a36Sopenharmony_ci|
8262306a36Sopenharmony_ciena:
8362306a36Sopenharmony_ci	btstb		#5,CMDREG1B(%a6) |if set, inst is move out
8462306a36Sopenharmony_ci	beq		not_out
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	bsrl		move_out
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cireport_snan:
8962306a36Sopenharmony_ci	moveb		(%a7),VER_TMP(%a6)
9062306a36Sopenharmony_ci	cmpib		#VER_40,(%a7)	|test for orig unimp frame
9162306a36Sopenharmony_ci	bnes		ck_rev
9262306a36Sopenharmony_ci	moveql		#13,%d0		|need to zero 14 lwords
9362306a36Sopenharmony_ci	bras		rep_con
9462306a36Sopenharmony_cick_rev:
9562306a36Sopenharmony_ci	moveql		#11,%d0		|need to zero 12 lwords
9662306a36Sopenharmony_cirep_con:
9762306a36Sopenharmony_ci	clrl		(%a7)
9862306a36Sopenharmony_ciloop1:
9962306a36Sopenharmony_ci	clrl		-(%a7)		|clear and dec a7
10062306a36Sopenharmony_ci	dbra		%d0,loop1
10162306a36Sopenharmony_ci	moveb		VER_TMP(%a6),(%a7) |format a busy frame
10262306a36Sopenharmony_ci	moveb		#BUSY_SIZE-4,1(%a7)
10362306a36Sopenharmony_ci	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
10462306a36Sopenharmony_ci	orl		#sx_mask,E_BYTE(%a6)
10562306a36Sopenharmony_ci	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
10662306a36Sopenharmony_ci	fmovemx	USER_FP0(%a6),%fp0-%fp3
10762306a36Sopenharmony_ci	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
10862306a36Sopenharmony_ci	frestore	(%a7)+
10962306a36Sopenharmony_ci	unlk		%a6
11062306a36Sopenharmony_ci	bral		real_snan
11162306a36Sopenharmony_ci|
11262306a36Sopenharmony_ci| Exit snan handler by expanding the unimp frame into a busy frame
11362306a36Sopenharmony_ci|
11462306a36Sopenharmony_ciend_snan:
11562306a36Sopenharmony_ci	bclrb		#E1,E_BYTE(%a6)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	moveb		(%a7),VER_TMP(%a6)
11862306a36Sopenharmony_ci	cmpib		#VER_40,(%a7)	|test for orig unimp frame
11962306a36Sopenharmony_ci	bnes		ck_rev2
12062306a36Sopenharmony_ci	moveql		#13,%d0		|need to zero 14 lwords
12162306a36Sopenharmony_ci	bras		rep_con2
12262306a36Sopenharmony_cick_rev2:
12362306a36Sopenharmony_ci	moveql		#11,%d0		|need to zero 12 lwords
12462306a36Sopenharmony_cirep_con2:
12562306a36Sopenharmony_ci	clrl		(%a7)
12662306a36Sopenharmony_ciloop2:
12762306a36Sopenharmony_ci	clrl		-(%a7)		|clear and dec a7
12862306a36Sopenharmony_ci	dbra		%d0,loop2
12962306a36Sopenharmony_ci	moveb		VER_TMP(%a6),(%a7) |format a busy frame
13062306a36Sopenharmony_ci	moveb		#BUSY_SIZE-4,1(%a7) |write busy size
13162306a36Sopenharmony_ci	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
13262306a36Sopenharmony_ci	orl		#sx_mask,E_BYTE(%a6)
13362306a36Sopenharmony_ci	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
13462306a36Sopenharmony_ci	fmovemx	USER_FP0(%a6),%fp0-%fp3
13562306a36Sopenharmony_ci	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
13662306a36Sopenharmony_ci	frestore	(%a7)+
13762306a36Sopenharmony_ci	unlk		%a6
13862306a36Sopenharmony_ci	bral		fpsp_done
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci|
14162306a36Sopenharmony_ci| Move_out
14262306a36Sopenharmony_ci|
14362306a36Sopenharmony_cimove_out:
14462306a36Sopenharmony_ci	movel		EXC_EA(%a6),%a0	|get <ea> from exc frame
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	bfextu		CMDREG1B(%a6){#3:#3},%d0 |move rx field to d0{2:0}
14762306a36Sopenharmony_ci	cmpil		#0,%d0		|check for long
14862306a36Sopenharmony_ci	beqs		sto_long	|branch if move_out long
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	cmpil		#4,%d0		|check for word
15162306a36Sopenharmony_ci	beqs		sto_word	|branch if move_out word
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	cmpil		#6,%d0		|check for byte
15462306a36Sopenharmony_ci	beqs		sto_byte	|branch if move_out byte
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci|
15762306a36Sopenharmony_ci| Not byte, word or long
15862306a36Sopenharmony_ci|
15962306a36Sopenharmony_ci	rts
16062306a36Sopenharmony_ci|
16162306a36Sopenharmony_ci| Get the 32 most significant bits of etemp mantissa
16262306a36Sopenharmony_ci|
16362306a36Sopenharmony_cisto_long:
16462306a36Sopenharmony_ci	movel		ETEMP_HI(%a6),%d1
16562306a36Sopenharmony_ci	movel		#4,%d0		|load byte count
16662306a36Sopenharmony_ci|
16762306a36Sopenharmony_ci| Set signalling nan bit
16862306a36Sopenharmony_ci|
16962306a36Sopenharmony_ci	bsetl		#30,%d1
17062306a36Sopenharmony_ci|
17162306a36Sopenharmony_ci| Store to the users destination address
17262306a36Sopenharmony_ci|
17362306a36Sopenharmony_ci	tstl		%a0		|check if <ea> is 0
17462306a36Sopenharmony_ci	beqs		wrt_dn		|destination is a data register
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	movel		%d1,-(%a7)	|move the snan onto the stack
17762306a36Sopenharmony_ci	movel		%a0,%a1		|load dest addr into a1
17862306a36Sopenharmony_ci	movel		%a7,%a0		|load src addr of snan into a0
17962306a36Sopenharmony_ci	bsrl		mem_write	|write snan to user memory
18062306a36Sopenharmony_ci	movel		(%a7)+,%d1	|clear off stack
18162306a36Sopenharmony_ci	rts
18262306a36Sopenharmony_ci|
18362306a36Sopenharmony_ci| Get the 16 most significant bits of etemp mantissa
18462306a36Sopenharmony_ci|
18562306a36Sopenharmony_cisto_word:
18662306a36Sopenharmony_ci	movel		ETEMP_HI(%a6),%d1
18762306a36Sopenharmony_ci	movel		#2,%d0		|load byte count
18862306a36Sopenharmony_ci|
18962306a36Sopenharmony_ci| Set signalling nan bit
19062306a36Sopenharmony_ci|
19162306a36Sopenharmony_ci	bsetl		#30,%d1
19262306a36Sopenharmony_ci|
19362306a36Sopenharmony_ci| Store to the users destination address
19462306a36Sopenharmony_ci|
19562306a36Sopenharmony_ci	tstl		%a0		|check if <ea> is 0
19662306a36Sopenharmony_ci	beqs		wrt_dn		|destination is a data register
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	movel		%d1,-(%a7)	|move the snan onto the stack
19962306a36Sopenharmony_ci	movel		%a0,%a1		|load dest addr into a1
20062306a36Sopenharmony_ci	movel		%a7,%a0		|point to low word
20162306a36Sopenharmony_ci	bsrl		mem_write	|write snan to user memory
20262306a36Sopenharmony_ci	movel		(%a7)+,%d1	|clear off stack
20362306a36Sopenharmony_ci	rts
20462306a36Sopenharmony_ci|
20562306a36Sopenharmony_ci| Get the 8 most significant bits of etemp mantissa
20662306a36Sopenharmony_ci|
20762306a36Sopenharmony_cisto_byte:
20862306a36Sopenharmony_ci	movel		ETEMP_HI(%a6),%d1
20962306a36Sopenharmony_ci	movel		#1,%d0		|load byte count
21062306a36Sopenharmony_ci|
21162306a36Sopenharmony_ci| Set signalling nan bit
21262306a36Sopenharmony_ci|
21362306a36Sopenharmony_ci	bsetl		#30,%d1
21462306a36Sopenharmony_ci|
21562306a36Sopenharmony_ci| Store to the users destination address
21662306a36Sopenharmony_ci|
21762306a36Sopenharmony_ci	tstl		%a0		|check if <ea> is 0
21862306a36Sopenharmony_ci	beqs		wrt_dn		|destination is a data register
21962306a36Sopenharmony_ci	movel		%d1,-(%a7)	|move the snan onto the stack
22062306a36Sopenharmony_ci	movel		%a0,%a1		|load dest addr into a1
22162306a36Sopenharmony_ci	movel		%a7,%a0		|point to source byte
22262306a36Sopenharmony_ci	bsrl		mem_write	|write snan to user memory
22362306a36Sopenharmony_ci	movel		(%a7)+,%d1	|clear off stack
22462306a36Sopenharmony_ci	rts
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci|
22762306a36Sopenharmony_ci|	wrt_dn --- write to a data register
22862306a36Sopenharmony_ci|
22962306a36Sopenharmony_ci|	We get here with D1 containing the data to write and D0 the
23062306a36Sopenharmony_ci|	number of bytes to write: 1=byte,2=word,4=long.
23162306a36Sopenharmony_ci|
23262306a36Sopenharmony_ciwrt_dn:
23362306a36Sopenharmony_ci	movel		%d1,L_SCR1(%a6)	|data
23462306a36Sopenharmony_ci	movel		%d0,-(%a7)	|size
23562306a36Sopenharmony_ci	bsrl		get_fline	|returns fline word in d0
23662306a36Sopenharmony_ci	movel		%d0,%d1
23762306a36Sopenharmony_ci	andil		#0x7,%d1		|d1 now holds register number
23862306a36Sopenharmony_ci	movel		(%sp)+,%d0	|get original size
23962306a36Sopenharmony_ci	cmpil		#4,%d0
24062306a36Sopenharmony_ci	beqs		wrt_long
24162306a36Sopenharmony_ci	cmpil		#2,%d0
24262306a36Sopenharmony_ci	bnes		wrt_byte
24362306a36Sopenharmony_ciwrt_word:
24462306a36Sopenharmony_ci	orl		#0x8,%d1
24562306a36Sopenharmony_ci	bral		reg_dest
24662306a36Sopenharmony_ciwrt_long:
24762306a36Sopenharmony_ci	orl		#0x10,%d1
24862306a36Sopenharmony_ci	bral		reg_dest
24962306a36Sopenharmony_ciwrt_byte:
25062306a36Sopenharmony_ci	bral		reg_dest
25162306a36Sopenharmony_ci|
25262306a36Sopenharmony_ci| Check if it is a src nan or dst nan
25362306a36Sopenharmony_ci|
25462306a36Sopenharmony_cinot_out:
25562306a36Sopenharmony_ci	movel		DTAG(%a6),%d0
25662306a36Sopenharmony_ci	bfextu		%d0{#0:#3},%d0	|isolate dtag in lsbs
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	cmpib		#3,%d0		|check for nan in destination
25962306a36Sopenharmony_ci	bnes		issrc		|destination nan has priority
26062306a36Sopenharmony_cidst_nan:
26162306a36Sopenharmony_ci	btstb		#6,FPTEMP_HI(%a6) |check if dest nan is an snan
26262306a36Sopenharmony_ci	bnes		issrc		|no, so check source for snan
26362306a36Sopenharmony_ci	movew		FPTEMP_EX(%a6),%d0
26462306a36Sopenharmony_ci	bras		cont
26562306a36Sopenharmony_ciissrc:
26662306a36Sopenharmony_ci	movew		ETEMP_EX(%a6),%d0
26762306a36Sopenharmony_cicont:
26862306a36Sopenharmony_ci	btstl		#15,%d0		|test for sign of snan
26962306a36Sopenharmony_ci	beqs		clr_neg
27062306a36Sopenharmony_ci	bsetb		#neg_bit,FPSR_CC(%a6)
27162306a36Sopenharmony_ci	bra		report_snan
27262306a36Sopenharmony_ciclr_neg:
27362306a36Sopenharmony_ci	bclrb		#neg_bit,FPSR_CC(%a6)
27462306a36Sopenharmony_ci	bra		report_snan
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	|end
277