xref: /netbsd/sys/arch/m68k/fpsp/x_operr.sa (revision 456dff6c)
1*456dff6cSwiz*	$NetBSD: x_operr.sa,v 1.5 2001/09/16 16:34:32 wiz Exp $
257fb77a1Scgd
322ef5fa9Smycroft*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
422ef5fa9Smycroft*	M68000 Hi-Performance Microprocessor Division
522ef5fa9Smycroft*	M68040 Software Package
622ef5fa9Smycroft*
722ef5fa9Smycroft*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
822ef5fa9Smycroft*	All rights reserved.
922ef5fa9Smycroft*
1022ef5fa9Smycroft*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
1122ef5fa9Smycroft*	To the maximum extent permitted by applicable law,
1222ef5fa9Smycroft*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
1322ef5fa9Smycroft*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
1422ef5fa9Smycroft*	PARTICULAR PURPOSE and any warranty against infringement with
1522ef5fa9Smycroft*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
1622ef5fa9Smycroft*	and any accompanying written materials.
1722ef5fa9Smycroft*
1822ef5fa9Smycroft*	To the maximum extent permitted by applicable law,
1922ef5fa9Smycroft*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
2022ef5fa9Smycroft*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
2122ef5fa9Smycroft*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
2222ef5fa9Smycroft*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
2322ef5fa9Smycroft*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
2422ef5fa9Smycroft*	and support of the SOFTWARE.
2522ef5fa9Smycroft*
2622ef5fa9Smycroft*	You are hereby granted a copyright license to use, modify, and
2722ef5fa9Smycroft*	distribute the SOFTWARE so long as this entire notice is retained
2822ef5fa9Smycroft*	without alteration in any modified and/or redistributed versions,
2922ef5fa9Smycroft*	and that such modified versions are clearly identified as such.
3022ef5fa9Smycroft*	No licenses are granted by implication, estoppel or otherwise
3122ef5fa9Smycroft*	under any patents or trademarks of Motorola, Inc.
3222ef5fa9Smycroft
3322ef5fa9Smycroft*
3422ef5fa9Smycroft*	x_operr.sa 3.5 7/1/91
3522ef5fa9Smycroft*
3622ef5fa9Smycroft*	fpsp_operr --- FPSP handler for operand error exception
3722ef5fa9Smycroft*
3822ef5fa9Smycroft*	See 68040 User's Manual pp. 9-44f
3922ef5fa9Smycroft*
4022ef5fa9Smycroft* Note 1: For trap disabled 040 does the following:
4122ef5fa9Smycroft* If the dest is a fp reg, then an extended precision non_signaling
4222ef5fa9Smycroft* NAN is stored in the dest reg.  If the dest format is b, w, or l and
4322ef5fa9Smycroft* the source op is a NAN, then garbage is stored as the result (actually
4422ef5fa9Smycroft* the upper 32 bits of the mantissa are sent to the integer unit). If
4522ef5fa9Smycroft* the dest format is integer (b, w, l) and the operr is caused by
4622ef5fa9Smycroft* integer overflow, or the source op is inf, then the result stored is
4722ef5fa9Smycroft* garbage.
4822ef5fa9Smycroft* There are three cases in which operr is incorrectly signaled on the
4922ef5fa9Smycroft* 040.  This occurs for move_out of format b, w, or l for the largest
5022ef5fa9Smycroft* negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
5122ef5fa9Smycroft*
5222ef5fa9Smycroft*	  On opclass = 011 fmove.(b,w,l) that causes a conversion
5322ef5fa9Smycroft*	  overflow -> OPERR, the exponent in wbte (and fpte) is:
5422ef5fa9Smycroft*		byte    56 - (62 - exp)
5522ef5fa9Smycroft*		word    48 - (62 - exp)
5622ef5fa9Smycroft*		long    32 - (62 - exp)
5722ef5fa9Smycroft*
5822ef5fa9Smycroft*			where exp = (true exp) - 1
5922ef5fa9Smycroft*
6022ef5fa9Smycroft*  So, wbtemp and fptemp will contain the following on erroneoulsy
6122ef5fa9Smycroft*	  signalled operr:
6222ef5fa9Smycroft*			fpts = 1
6322ef5fa9Smycroft*			fpte = $4000  (15 bit externally)
6422ef5fa9Smycroft*		byte	fptm = $ffffffff ffffff80
6522ef5fa9Smycroft*		word	fptm = $ffffffff ffff8000
6622ef5fa9Smycroft*		long	fptm = $ffffffff 80000000
6722ef5fa9Smycroft*
6822ef5fa9Smycroft* Note 2: For trap enabled 040 does the following:
6922ef5fa9Smycroft* If the inst is move_out, then same as Note 1.
7022ef5fa9Smycroft* If the inst is not move_out, the dest is not modified.
7122ef5fa9Smycroft* The exceptional operand is not defined for integer overflow
7222ef5fa9Smycroft* during a move_out.
7322ef5fa9Smycroft*
7422ef5fa9Smycroft
7522ef5fa9SmycroftX_OPERR	IDNT    2,1 Motorola 040 Floating Point Software Package
7622ef5fa9Smycroft
7722ef5fa9Smycroft	section	8
7822ef5fa9Smycroft
7922ef5fa9Smycroft	include	fpsp.h
8022ef5fa9Smycroft
8122ef5fa9Smycroft	xref	mem_write
8222ef5fa9Smycroft	xref	real_operr
8322ef5fa9Smycroft	xref	real_inex
8422ef5fa9Smycroft	xref	get_fline
8522ef5fa9Smycroft	xref	fpsp_done
8622ef5fa9Smycroft	xref	reg_dest
8722ef5fa9Smycroft
8822ef5fa9Smycroft	xdef	fpsp_operr
8922ef5fa9Smycroftfpsp_operr:
9022ef5fa9Smycroft*
9122ef5fa9Smycroft	link		a6,#-LOCAL_SIZE
9222ef5fa9Smycroft	fsave		-(a7)
9322ef5fa9Smycroft	movem.l		d0-d1/a0-a1,USER_DA(a6)
9422ef5fa9Smycroft	fmovem.x	fp0-fp3,USER_FP0(a6)
9522ef5fa9Smycroft	fmovem.l	fpcr/fpsr/fpiar,USER_FPCR(a6)
9622ef5fa9Smycroft
9722ef5fa9Smycroft*
9822ef5fa9Smycroft* Check if this is an opclass 3 instruction.
9922ef5fa9Smycroft*  If so, fall through, else branch to operr_end
10022ef5fa9Smycroft*
10122ef5fa9Smycroft	btst.b	#TFLAG,T_BYTE(a6)
10222ef5fa9Smycroft	beq.b	operr_end
10322ef5fa9Smycroft
10422ef5fa9Smycroft*
10522ef5fa9Smycroft* If the destination size is B,W,or L, the operr must be
10622ef5fa9Smycroft* handled here.
10722ef5fa9Smycroft*
10822ef5fa9Smycroft	move.l	CMDREG1B(a6),d0
10922ef5fa9Smycroft	bfextu	d0{3:3},d0	;0=long, 4=word, 6=byte
110eddb30abSmycroft	tst.b	d0		;determine size; check long
11122ef5fa9Smycroft	beq.w	operr_long
11222ef5fa9Smycroft	cmpi.b	#4,d0		;check word
11322ef5fa9Smycroft	beq.w	operr_word
11422ef5fa9Smycroft	cmpi.b	#6,d0		;check byte
11522ef5fa9Smycroft	beq.w	operr_byte
11622ef5fa9Smycroft
11722ef5fa9Smycroft*
11822ef5fa9Smycroft* The size is not B,W,or L, so the operr is handled by the
11922ef5fa9Smycroft* kernel handler.  Set the operr bits and clean up, leaving
12022ef5fa9Smycroft* only the integer exception frame on the stack, and the
12122ef5fa9Smycroft* fpu in the original exceptional state.
12222ef5fa9Smycroft*
12322ef5fa9Smycroftoperr_end:
12422ef5fa9Smycroft	bset.b		#operr_bit,FPSR_EXCEPT(a6)
12522ef5fa9Smycroft	bset.b		#aiop_bit,FPSR_AEXCEPT(a6)
12622ef5fa9Smycroft
12722ef5fa9Smycroft	movem.l		USER_DA(a6),d0-d1/a0-a1
12822ef5fa9Smycroft	fmovem.x	USER_FP0(a6),fp0-fp3
12922ef5fa9Smycroft	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
13022ef5fa9Smycroft	frestore	(a7)+
13122ef5fa9Smycroft	unlk		a6
13222ef5fa9Smycroft	bra.l		real_operr
13322ef5fa9Smycroft
13422ef5fa9Smycroftoperr_long:
13522ef5fa9Smycroft	moveq.l	#4,d1		;write size to d1
13622ef5fa9Smycroft	move.b	STAG(a6),d0	;test stag for nan
13722ef5fa9Smycroft	andi.b	#$e0,d0		;clr all but tag
13822ef5fa9Smycroft	cmpi.b	#$60,d0		;check for nan
13922ef5fa9Smycroft	beq	operr_nan
14022ef5fa9Smycroft	cmpi.l	#$80000000,FPTEMP_LO(a6) ;test if ls lword is special
14122ef5fa9Smycroft	bne.b	chklerr		;if not equal, check for incorrect operr
14222ef5fa9Smycroft	bsr	check_upper	;check if exp and ms mant are special
14322ef5fa9Smycroft	tst.l	d0
14422ef5fa9Smycroft	bne.b	chklerr		;if d0 is true, check for incorrect operr
14522ef5fa9Smycroft	move.l	#$80000000,d0	;store special case result
14622ef5fa9Smycroft	bsr	operr_store
14722ef5fa9Smycroft	bra.w	not_enabled	;clean and exit
14822ef5fa9Smycroft*
14922ef5fa9Smycroft*	CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
15022ef5fa9Smycroft*
15122ef5fa9Smycroftchklerr:
15222ef5fa9Smycroft	move.w	FPTEMP_EX(a6),d0
15322ef5fa9Smycroft	and.w	#$7FFF,d0	;ignore sign bit
15422ef5fa9Smycroft	cmp.w	#$3FFE,d0	;this is the only possible exponent value
15522ef5fa9Smycroft	bne.b	chklerr2
15622ef5fa9Smycroftfixlong:
15722ef5fa9Smycroft	move.l	FPTEMP_LO(a6),d0
15822ef5fa9Smycroft	bsr	operr_store
15922ef5fa9Smycroft	bra.w	not_enabled
16022ef5fa9Smycroftchklerr2:
16122ef5fa9Smycroft	move.w	FPTEMP_EX(a6),d0
16222ef5fa9Smycroft	and.w	#$7FFF,d0	;ignore sign bit
16322ef5fa9Smycroft	cmp.w	#$4000,d0
164d5b1b6a1Smycroft	bcc.w	store_max	;exponent out of range
16522ef5fa9Smycroft
16622ef5fa9Smycroft	move.l	FPTEMP_LO(a6),d0
16722ef5fa9Smycroft	and.l	#$7FFF0000,d0	;look for all 1's on bits 30-16
16822ef5fa9Smycroft	cmp.l	#$7FFF0000,d0
16922ef5fa9Smycroft	beq.b	fixlong
17022ef5fa9Smycroft
17122ef5fa9Smycroft	tst.l	FPTEMP_LO(a6)
17222ef5fa9Smycroft	bpl.b	chklepos
17322ef5fa9Smycroft	cmp.l	#$FFFFFFFF,FPTEMP_HI(a6)
17422ef5fa9Smycroft	beq.b	fixlong
17522ef5fa9Smycroft	bra.w	store_max
17622ef5fa9Smycroftchklepos:
17722ef5fa9Smycroft	tst.l	FPTEMP_HI(a6)
17822ef5fa9Smycroft	beq.b	fixlong
17922ef5fa9Smycroft	bra.w	store_max
18022ef5fa9Smycroft
18122ef5fa9Smycroftoperr_word:
18222ef5fa9Smycroft	moveq.l	#2,d1		;write size to d1
18322ef5fa9Smycroft	move.b	STAG(a6),d0	;test stag for nan
18422ef5fa9Smycroft	andi.b	#$e0,d0		;clr all but tag
18522ef5fa9Smycroft	cmpi.b	#$60,d0		;check for nan
18622ef5fa9Smycroft	beq.w	operr_nan
18722ef5fa9Smycroft	cmpi.l	#$ffff8000,FPTEMP_LO(a6) ;test if ls lword is special
18822ef5fa9Smycroft	bne.b	chkwerr		;if not equal, check for incorrect operr
18922ef5fa9Smycroft	bsr	check_upper	;check if exp and ms mant are special
19022ef5fa9Smycroft	tst.l	d0
19122ef5fa9Smycroft	bne.b	chkwerr		;if d0 is true, check for incorrect operr
19222ef5fa9Smycroft	move.l	#$80000000,d0	;store special case result
19322ef5fa9Smycroft	bsr	operr_store
19422ef5fa9Smycroft	bra.w	not_enabled	;clean and exit
19522ef5fa9Smycroft*
19622ef5fa9Smycroft*	CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
19722ef5fa9Smycroft*
19822ef5fa9Smycroftchkwerr:
19922ef5fa9Smycroft	move.w	FPTEMP_EX(a6),d0
20022ef5fa9Smycroft	and.w	#$7FFF,d0	;ignore sign bit
20122ef5fa9Smycroft	cmp.w	#$3FFE,d0	;this is the only possible exponent value
20222ef5fa9Smycroft	bne.b	store_max
20322ef5fa9Smycroft	move.l	FPTEMP_LO(a6),d0
20422ef5fa9Smycroft	swap	d0
20522ef5fa9Smycroft	bsr	operr_store
20622ef5fa9Smycroft	bra.w	not_enabled
20722ef5fa9Smycroft
20822ef5fa9Smycroftoperr_byte:
20922ef5fa9Smycroft	moveq.l	#1,d1		;write size to d1
21022ef5fa9Smycroft	move.b	STAG(a6),d0	;test stag for nan
21122ef5fa9Smycroft	andi.b	#$e0,d0		;clr all but tag
21222ef5fa9Smycroft	cmpi.b	#$60,d0		;check for nan
21322ef5fa9Smycroft	beq.b	operr_nan
21422ef5fa9Smycroft	cmpi.l	#$ffffff80,FPTEMP_LO(a6) ;test if ls lword is special
21522ef5fa9Smycroft	bne.b	chkberr		;if not equal, check for incorrect operr
21622ef5fa9Smycroft	bsr	check_upper	;check if exp and ms mant are special
21722ef5fa9Smycroft	tst.l	d0
21822ef5fa9Smycroft	bne.b	chkberr		;if d0 is true, check for incorrect operr
21922ef5fa9Smycroft	move.l	#$80000000,d0	;store special case result
22022ef5fa9Smycroft	bsr	operr_store
22122ef5fa9Smycroft	bra.w	not_enabled	;clean and exit
22222ef5fa9Smycroft*
22322ef5fa9Smycroft*	CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
22422ef5fa9Smycroft*
22522ef5fa9Smycroftchkberr:
22622ef5fa9Smycroft	move.w	FPTEMP_EX(a6),d0
22722ef5fa9Smycroft	and.w	#$7FFF,d0	;ignore sign bit
22822ef5fa9Smycroft	cmp.w	#$3FFE,d0	;this is the only possible exponent value
22922ef5fa9Smycroft	bne.b	store_max
23022ef5fa9Smycroft	move.l	FPTEMP_LO(a6),d0
23122ef5fa9Smycroft	asl.l	#8,d0
23222ef5fa9Smycroft	swap	d0
23322ef5fa9Smycroft	bsr	operr_store
23422ef5fa9Smycroft	bra.w	not_enabled
23522ef5fa9Smycroft
23622ef5fa9Smycroft*
23722ef5fa9Smycroft* This operr condition is not of the special case.  Set operr
23822ef5fa9Smycroft* and aiop and write the portion of the nan to memory for the
23922ef5fa9Smycroft* given size.
24022ef5fa9Smycroft*
24122ef5fa9Smycroftoperr_nan:
24222ef5fa9Smycroft	or.l	#opaop_mask,USER_FPSR(a6) ;set operr & aiop
24322ef5fa9Smycroft
24422ef5fa9Smycroft	move.l	ETEMP_HI(a6),d0	;output will be from upper 32 bits
24522ef5fa9Smycroft	bsr	operr_store
24622ef5fa9Smycroft	bra	end_operr
24722ef5fa9Smycroft*
24822ef5fa9Smycroft* Store_max loads the max pos or negative for the size, sets
24922ef5fa9Smycroft* the operr and aiop bits, and clears inex and ainex, incorrectly
25022ef5fa9Smycroft* set by the 040.
25122ef5fa9Smycroft*
25222ef5fa9Smycroftstore_max:
25322ef5fa9Smycroft	or.l	#opaop_mask,USER_FPSR(a6) ;set operr & aiop
25422ef5fa9Smycroft	bclr.b	#inex2_bit,FPSR_EXCEPT(a6)
25522ef5fa9Smycroft	bclr.b	#ainex_bit,FPSR_AEXCEPT(a6)
25622ef5fa9Smycroft	fmove.l	#0,FPSR
25722ef5fa9Smycroft
25822ef5fa9Smycroft	tst.w	FPTEMP_EX(a6)	;check sign
25922ef5fa9Smycroft	blt.b	load_neg
26022ef5fa9Smycroft	move.l	#$7fffffff,d0
26122ef5fa9Smycroft	bsr	operr_store
26222ef5fa9Smycroft	bra	end_operr
26322ef5fa9Smycroftload_neg:
26422ef5fa9Smycroft	move.l	#$80000000,d0
26522ef5fa9Smycroft	bsr	operr_store
26622ef5fa9Smycroft	bra	end_operr
26722ef5fa9Smycroft
26822ef5fa9Smycroft*
26922ef5fa9Smycroft* This routine stores the data in d0, for the given size in d1,
27022ef5fa9Smycroft* to memory or data register as required.  A read of the fline
27122ef5fa9Smycroft* is required to determine the destination.
27222ef5fa9Smycroft*
27322ef5fa9Smycroftoperr_store:
27422ef5fa9Smycroft	move.l	d0,L_SCR1(a6)	;move write data to L_SCR1
27522ef5fa9Smycroft	move.l	d1,-(a7)	;save register size
27622ef5fa9Smycroft	bsr.l	get_fline	;fline returned in d0
27722ef5fa9Smycroft	move.l	(a7)+,d1
27822ef5fa9Smycroft	bftst	d0{26:3}		;if mode is zero, dest is Dn
27922ef5fa9Smycroft	bne.b	dest_mem
28022ef5fa9Smycroft*
28122ef5fa9Smycroft* Destination is Dn.  Get register number from d0. Data is on
28222ef5fa9Smycroft* the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
28322ef5fa9Smycroft*
28422ef5fa9Smycroft	andi.l	#7,d0		;isolate register number
28522ef5fa9Smycroft	cmpi.l	#4,d1
28622ef5fa9Smycroft	beq.b	op_long		;the most frequent case
28722ef5fa9Smycroft	cmpi.l	#2,d1
28822ef5fa9Smycroft	bne.b	op_con
28922ef5fa9Smycroft	or.l	#8,d0
29022ef5fa9Smycroft	bra.b	op_con
29122ef5fa9Smycroftop_long:
29222ef5fa9Smycroft	or.l	#$10,d0
29322ef5fa9Smycroftop_con:
29422ef5fa9Smycroft	move.l	d0,d1		;format size:reg for reg_dest
29522ef5fa9Smycroft	bra.l	reg_dest	;call to reg_dest returns to caller
29622ef5fa9Smycroft*				;of operr_store
29722ef5fa9Smycroft*
29822ef5fa9Smycroft* Destination is memory.  Get <ea> from integer exception frame
29922ef5fa9Smycroft* and call mem_write.
30022ef5fa9Smycroft*
30122ef5fa9Smycroftdest_mem:
30222ef5fa9Smycroft	lea.l	L_SCR1(a6),a0	;put ptr to write data in a0
30322ef5fa9Smycroft	move.l	EXC_EA(a6),a1	;put user destination address in a1
30422ef5fa9Smycroft	move.l	d1,d0		;put size in d0
30522ef5fa9Smycroft	bsr.l	mem_write
30622ef5fa9Smycroft	rts
30722ef5fa9Smycroft*
30822ef5fa9Smycroft* Check the exponent for $c000 and the upper 32 bits of the
30922ef5fa9Smycroft* mantissa for $ffffffff.  If both are true, return d0 clr
31022ef5fa9Smycroft* and store the lower n bits of the least lword of FPTEMP
31122ef5fa9Smycroft* to d0 for write out.  If not, it is a real operr, and set d0.
31222ef5fa9Smycroft*
31322ef5fa9Smycroftcheck_upper:
31422ef5fa9Smycroft	cmpi.l	#$ffffffff,FPTEMP_HI(a6) ;check if first byte is all 1's
31522ef5fa9Smycroft	bne.b	true_operr	;if not all 1's then was true operr
31622ef5fa9Smycroft	cmpi.w	#$c000,FPTEMP_EX(a6) ;check if incorrectly signalled
31722ef5fa9Smycroft	beq.b	not_true_operr	;branch if not true operr
31822ef5fa9Smycroft	cmpi.w	#$bfff,FPTEMP_EX(a6) ;check if incorrectly signalled
31922ef5fa9Smycroft	beq.b	not_true_operr	;branch if not true operr
32022ef5fa9Smycrofttrue_operr:
32122ef5fa9Smycroft	move.l	#1,d0		;signal real operr
32222ef5fa9Smycroft	rts
32322ef5fa9Smycroftnot_true_operr:
32422ef5fa9Smycroft	clr.l	d0		;signal no real operr
32522ef5fa9Smycroft	rts
32622ef5fa9Smycroft
32722ef5fa9Smycroft*
32822ef5fa9Smycroft* End_operr tests for operr enabled.  If not, it cleans up the stack
32922ef5fa9Smycroft* and does an rte.  If enabled, it cleans up the stack and branches
33022ef5fa9Smycroft* to the kernel operr handler with only the integer exception
33122ef5fa9Smycroft* frame on the stack and the fpu in the original exceptional state
33222ef5fa9Smycroft* with correct data written to the destination.
33322ef5fa9Smycroft*
33422ef5fa9Smycroftend_operr:
33522ef5fa9Smycroft	btst.b		#operr_bit,FPCR_ENABLE(a6)
33622ef5fa9Smycroft	beq.b		not_enabled
33722ef5fa9Smycroftenabled:
33822ef5fa9Smycroft	movem.l		USER_DA(a6),d0-d1/a0-a1
33922ef5fa9Smycroft	fmovem.x	USER_FP0(a6),fp0-fp3
34022ef5fa9Smycroft	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
34122ef5fa9Smycroft	frestore	(a7)+
34222ef5fa9Smycroft	unlk		a6
34322ef5fa9Smycroft	bra.l		real_operr
34422ef5fa9Smycroft
34522ef5fa9Smycroftnot_enabled:
34622ef5fa9Smycroft*
34722ef5fa9Smycroft* It is possible to have either inex2 or inex1 exceptions with the
34822ef5fa9Smycroft* operr.  If the inex enable bit is set in the FPCR, and either
349*456dff6cSwiz* inex2 or inex1 occurred, we must clean up and branch to the
35022ef5fa9Smycroft* real inex handler.
35122ef5fa9Smycroft*
35222ef5fa9Smycroftck_inex:
35322ef5fa9Smycroft	move.b	FPCR_ENABLE(a6),d0
35422ef5fa9Smycroft	and.b	FPSR_EXCEPT(a6),d0
35522ef5fa9Smycroft	andi.b	#$3,d0
35622ef5fa9Smycroft	beq.w	operr_exit
35722ef5fa9Smycroft*
35822ef5fa9Smycroft* Inexact enabled and reported, and we must take an inexact exception.
35922ef5fa9Smycroft*
36022ef5fa9Smycrofttake_inex:
36122ef5fa9Smycroft	move.b		#INEX_VEC,EXC_VEC+1(a6)
36222ef5fa9Smycroft	move.l		USER_FPSR(a6),FPSR_SHADOW(a6)
36322ef5fa9Smycroft	or.l		#sx_mask,E_BYTE(a6)
36422ef5fa9Smycroft	movem.l		USER_DA(a6),d0-d1/a0-a1
36522ef5fa9Smycroft	fmovem.x	USER_FP0(a6),fp0-fp3
36622ef5fa9Smycroft	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
36722ef5fa9Smycroft	frestore	(a7)+
36822ef5fa9Smycroft	unlk		a6
36922ef5fa9Smycroft	bra.l		real_inex
37022ef5fa9Smycroft*
37122ef5fa9Smycroft* Since operr is only an E1 exception, there is no need to frestore
37222ef5fa9Smycroft* any state back to the fpu.
37322ef5fa9Smycroft*
37422ef5fa9Smycroftoperr_exit:
37522ef5fa9Smycroft	movem.l		USER_DA(a6),d0-d1/a0-a1
37622ef5fa9Smycroft	fmovem.x	USER_FP0(a6),fp0-fp3
37722ef5fa9Smycroft	fmovem.l	USER_FPCR(a6),fpcr/fpsr/fpiar
37822ef5fa9Smycroft	unlk		a6
37922ef5fa9Smycroft	bra.l		fpsp_done
38022ef5fa9Smycroft
38122ef5fa9Smycroft	end
382