xref: /linux/arch/m68k/fpsp040/sint.S (revision e5451c8f8330e03ad3cfa16048b4daf961af434f)
11da177e4SLinus Torvalds|
21da177e4SLinus Torvalds|	sint.sa 3.1 12/10/90
31da177e4SLinus Torvalds|
41da177e4SLinus Torvalds|	The entry point sINT computes the rounded integer
51da177e4SLinus Torvalds|	equivalent of the input argument, sINTRZ computes
61da177e4SLinus Torvalds|	the integer rounded to zero of the input argument.
71da177e4SLinus Torvalds|
81da177e4SLinus Torvalds|	Entry points sint and sintrz are called from do_func
91da177e4SLinus Torvalds|	to emulate the fint and fintrz unimplemented instructions,
101da177e4SLinus Torvalds|	respectively.  Entry point sintdo is used by bindec.
111da177e4SLinus Torvalds|
121da177e4SLinus Torvalds|	Input: (Entry points sint and sintrz) Double-extended
131da177e4SLinus Torvalds|		number X in the ETEMP space in the floating-point
141da177e4SLinus Torvalds|		save stack.
151da177e4SLinus Torvalds|	       (Entry point sintdo) Double-extended number X in
161da177e4SLinus Torvalds|		location pointed to by the address register a0.
171da177e4SLinus Torvalds|	       (Entry point sintd) Double-extended denormalized
181da177e4SLinus Torvalds|		number X in the ETEMP space in the floating-point
191da177e4SLinus Torvalds|		save stack.
201da177e4SLinus Torvalds|
211da177e4SLinus Torvalds|	Output: The function returns int(X) or intrz(X) in fp0.
221da177e4SLinus Torvalds|
231da177e4SLinus Torvalds|	Modifies: fp0.
241da177e4SLinus Torvalds|
251da177e4SLinus Torvalds|	Algorithm: (sint and sintrz)
261da177e4SLinus Torvalds|
271da177e4SLinus Torvalds|	1. If exp(X) >= 63, return X.
281da177e4SLinus Torvalds|	   If exp(X) < 0, return +/- 0 or +/- 1, according to
291da177e4SLinus Torvalds|	   the rounding mode.
301da177e4SLinus Torvalds|
311da177e4SLinus Torvalds|	2. (X is in range) set rsc = 63 - exp(X). Unnormalize the
321da177e4SLinus Torvalds|	   result to the exponent $403e.
331da177e4SLinus Torvalds|
341da177e4SLinus Torvalds|	3. Round the result in the mode given in USER_FPCR. For
351da177e4SLinus Torvalds|	   sintrz, force round-to-zero mode.
361da177e4SLinus Torvalds|
371da177e4SLinus Torvalds|	4. Normalize the rounded result; store in fp0.
381da177e4SLinus Torvalds|
391da177e4SLinus Torvalds|	For the denormalized cases, force the correct result
401da177e4SLinus Torvalds|	for the given sign and rounding mode.
411da177e4SLinus Torvalds|
421da177e4SLinus Torvalds|		        Sign(X)
431da177e4SLinus Torvalds|		RMODE   +    -
441da177e4SLinus Torvalds|		-----  --------
451da177e4SLinus Torvalds|		 RN    +0   -0
461da177e4SLinus Torvalds|		 RZ    +0   -0
471da177e4SLinus Torvalds|		 RM    +0   -1
481da177e4SLinus Torvalds|		 RP    +1   -0
491da177e4SLinus Torvalds|
501da177e4SLinus Torvalds|
511da177e4SLinus Torvalds|		Copyright (C) Motorola, Inc. 1990
521da177e4SLinus Torvalds|			All Rights Reserved
531da177e4SLinus Torvalds|
54*e00d82d0SMatt Waddel|       For details on the license for this file, please see the
55*e00d82d0SMatt Waddel|       file, README, in this same directory.
561da177e4SLinus Torvalds
571da177e4SLinus Torvalds|SINT    idnt    2,1 | Motorola 040 Floating Point Software Package
581da177e4SLinus Torvalds
591da177e4SLinus Torvalds	|section	8
601da177e4SLinus Torvalds
611da177e4SLinus Torvalds#include "fpsp.h"
621da177e4SLinus Torvalds
631da177e4SLinus Torvalds	|xref	dnrm_lp
641da177e4SLinus Torvalds	|xref	nrm_set
651da177e4SLinus Torvalds	|xref	round
661da177e4SLinus Torvalds	|xref	t_inx2
671da177e4SLinus Torvalds	|xref	ld_pone
681da177e4SLinus Torvalds	|xref	ld_mone
691da177e4SLinus Torvalds	|xref	ld_pzero
701da177e4SLinus Torvalds	|xref	ld_mzero
711da177e4SLinus Torvalds	|xref	snzrinx
721da177e4SLinus Torvalds
731da177e4SLinus Torvalds|
741da177e4SLinus Torvalds|	FINT
751da177e4SLinus Torvalds|
761da177e4SLinus Torvalds	.global	sint
771da177e4SLinus Torvaldssint:
781da177e4SLinus Torvalds	bfextu	FPCR_MODE(%a6){#2:#2},%d1	|use user's mode for rounding
791da177e4SLinus Torvalds|					;implicitly has extend precision
801da177e4SLinus Torvalds|					;in upper word.
811da177e4SLinus Torvalds	movel	%d1,L_SCR1(%a6)		|save mode bits
821da177e4SLinus Torvalds	bras	sintexc
831da177e4SLinus Torvalds
841da177e4SLinus Torvalds|
851da177e4SLinus Torvalds|	FINT with extended denorm inputs.
861da177e4SLinus Torvalds|
871da177e4SLinus Torvalds	.global	sintd
881da177e4SLinus Torvaldssintd:
891da177e4SLinus Torvalds	btstb	#5,FPCR_MODE(%a6)
901da177e4SLinus Torvalds	beq	snzrinx		|if round nearest or round zero, +/- 0
911da177e4SLinus Torvalds	btstb	#4,FPCR_MODE(%a6)
921da177e4SLinus Torvalds	beqs	rnd_mns
931da177e4SLinus Torvaldsrnd_pls:
941da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)
951da177e4SLinus Torvalds	bnes	sintmz
961da177e4SLinus Torvalds	bsr	ld_pone		|if round plus inf and pos, answer is +1
971da177e4SLinus Torvalds	bra	t_inx2
981da177e4SLinus Torvaldsrnd_mns:
991da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)
1001da177e4SLinus Torvalds	beqs	sintpz
1011da177e4SLinus Torvalds	bsr	ld_mone		|if round mns inf and neg, answer is -1
1021da177e4SLinus Torvalds	bra	t_inx2
1031da177e4SLinus Torvaldssintpz:
1041da177e4SLinus Torvalds	bsr	ld_pzero
1051da177e4SLinus Torvalds	bra	t_inx2
1061da177e4SLinus Torvaldssintmz:
1071da177e4SLinus Torvalds	bsr	ld_mzero
1081da177e4SLinus Torvalds	bra	t_inx2
1091da177e4SLinus Torvalds
1101da177e4SLinus Torvalds|
1111da177e4SLinus Torvalds|	FINTRZ
1121da177e4SLinus Torvalds|
1131da177e4SLinus Torvalds	.global	sintrz
1141da177e4SLinus Torvaldssintrz:
1151da177e4SLinus Torvalds	movel	#1,L_SCR1(%a6)		|use rz mode for rounding
1161da177e4SLinus Torvalds|					;implicitly has extend precision
1171da177e4SLinus Torvalds|					;in upper word.
1181da177e4SLinus Torvalds	bras	sintexc
1191da177e4SLinus Torvalds|
1201da177e4SLinus Torvalds|	SINTDO
1211da177e4SLinus Torvalds|
1221da177e4SLinus Torvalds|	Input:	a0 points to an IEEE extended format operand
1231da177e4SLinus Torvalds|	Output:	fp0 has the result
1241da177e4SLinus Torvalds|
1251da177e4SLinus Torvalds| Exceptions:
1261da177e4SLinus Torvalds|
1271da177e4SLinus Torvalds| If the subroutine results in an inexact operation, the inx2 and
1281da177e4SLinus Torvalds| ainx bits in the USER_FPSR are set.
1291da177e4SLinus Torvalds|
1301da177e4SLinus Torvalds|
1311da177e4SLinus Torvalds	.global	sintdo
1321da177e4SLinus Torvaldssintdo:
1331da177e4SLinus Torvalds	bfextu	FPCR_MODE(%a6){#2:#2},%d1	|use user's mode for rounding
1341da177e4SLinus Torvalds|					;implicitly has ext precision
1351da177e4SLinus Torvalds|					;in upper word.
1361da177e4SLinus Torvalds	movel	%d1,L_SCR1(%a6)		|save mode bits
1371da177e4SLinus Torvalds|
1381da177e4SLinus Torvalds| Real work of sint is in sintexc
1391da177e4SLinus Torvalds|
1401da177e4SLinus Torvaldssintexc:
1411da177e4SLinus Torvalds	bclrb	#sign_bit,LOCAL_EX(%a0)	|convert to internal extended
1421da177e4SLinus Torvalds|					;format
1431da177e4SLinus Torvalds	sne	LOCAL_SGN(%a0)
1441da177e4SLinus Torvalds	cmpw	#0x403e,LOCAL_EX(%a0)	|check if (unbiased) exp > 63
1451da177e4SLinus Torvalds	bgts	out_rnge			|branch if exp < 63
1461da177e4SLinus Torvalds	cmpw	#0x3ffd,LOCAL_EX(%a0)	|check if (unbiased) exp < 0
1471da177e4SLinus Torvalds	bgt	in_rnge			|if 63 >= exp > 0, do calc
1481da177e4SLinus Torvalds|
1491da177e4SLinus Torvalds| Input is less than zero.  Restore sign, and check for directed
1501da177e4SLinus Torvalds| rounding modes.  L_SCR1 contains the rmode in the lower byte.
1511da177e4SLinus Torvalds|
1521da177e4SLinus Torvaldsun_rnge:
1531da177e4SLinus Torvalds	btstb	#1,L_SCR1+3(%a6)		|check for rn and rz
1541da177e4SLinus Torvalds	beqs	un_rnrz
1551da177e4SLinus Torvalds	tstb	LOCAL_SGN(%a0)		|check for sign
1561da177e4SLinus Torvalds	bnes	un_rmrp_neg
1571da177e4SLinus Torvalds|
1581da177e4SLinus Torvalds| Sign is +.  If rp, load +1.0, if rm, load +0.0
1591da177e4SLinus Torvalds|
1601da177e4SLinus Torvalds	cmpib	#3,L_SCR1+3(%a6)		|check for rp
1611da177e4SLinus Torvalds	beqs	un_ldpone		|if rp, load +1.0
1621da177e4SLinus Torvalds	bsr	ld_pzero		|if rm, load +0.0
1631da177e4SLinus Torvalds	bra	t_inx2
1641da177e4SLinus Torvaldsun_ldpone:
1651da177e4SLinus Torvalds	bsr	ld_pone
1661da177e4SLinus Torvalds	bra	t_inx2
1671da177e4SLinus Torvalds|
1681da177e4SLinus Torvalds| Sign is -.  If rm, load -1.0, if rp, load -0.0
1691da177e4SLinus Torvalds|
1701da177e4SLinus Torvaldsun_rmrp_neg:
1711da177e4SLinus Torvalds	cmpib	#2,L_SCR1+3(%a6)		|check for rm
1721da177e4SLinus Torvalds	beqs	un_ldmone		|if rm, load -1.0
1731da177e4SLinus Torvalds	bsr	ld_mzero		|if rp, load -0.0
1741da177e4SLinus Torvalds	bra	t_inx2
1751da177e4SLinus Torvaldsun_ldmone:
1761da177e4SLinus Torvalds	bsr	ld_mone
1771da177e4SLinus Torvalds	bra	t_inx2
1781da177e4SLinus Torvalds|
1791da177e4SLinus Torvalds| Rmode is rn or rz; return signed zero
1801da177e4SLinus Torvalds|
1811da177e4SLinus Torvaldsun_rnrz:
1821da177e4SLinus Torvalds	tstb	LOCAL_SGN(%a0)		|check for sign
1831da177e4SLinus Torvalds	bnes	un_rnrz_neg
1841da177e4SLinus Torvalds	bsr	ld_pzero
1851da177e4SLinus Torvalds	bra	t_inx2
1861da177e4SLinus Torvaldsun_rnrz_neg:
1871da177e4SLinus Torvalds	bsr	ld_mzero
1881da177e4SLinus Torvalds	bra	t_inx2
1891da177e4SLinus Torvalds
1901da177e4SLinus Torvalds|
1911da177e4SLinus Torvalds| Input is greater than 2^63.  All bits are significant.  Return
1921da177e4SLinus Torvalds| the input.
1931da177e4SLinus Torvalds|
1941da177e4SLinus Torvaldsout_rnge:
1951da177e4SLinus Torvalds	bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format
1961da177e4SLinus Torvalds	beqs	intps
1971da177e4SLinus Torvalds	bsetb	#sign_bit,LOCAL_EX(%a0)
1981da177e4SLinus Torvaldsintps:
1991da177e4SLinus Torvalds	fmovel	%fpcr,-(%sp)
2001da177e4SLinus Torvalds	fmovel	#0,%fpcr
2011da177e4SLinus Torvalds	fmovex LOCAL_EX(%a0),%fp0	|if exp > 63
2021da177e4SLinus Torvalds|					;then return X to the user
2031da177e4SLinus Torvalds|					;there are no fraction bits
2041da177e4SLinus Torvalds	fmovel	(%sp)+,%fpcr
2051da177e4SLinus Torvalds	rts
2061da177e4SLinus Torvalds
2071da177e4SLinus Torvaldsin_rnge:
2081da177e4SLinus Torvalds|					;shift off fraction bits
2091da177e4SLinus Torvalds	clrl	%d0			|clear d0 - initial g,r,s for
2101da177e4SLinus Torvalds|					;dnrm_lp
2111da177e4SLinus Torvalds	movel	#0x403e,%d1		|set threshold for dnrm_lp
2121da177e4SLinus Torvalds|					;assumes a0 points to operand
2131da177e4SLinus Torvalds	bsr	dnrm_lp
2141da177e4SLinus Torvalds|					;returns unnormalized number
2151da177e4SLinus Torvalds|					;pointed by a0
2161da177e4SLinus Torvalds|					;output d0 supplies g,r,s
2171da177e4SLinus Torvalds|					;used by round
2181da177e4SLinus Torvalds	movel	L_SCR1(%a6),%d1		|use selected rounding mode
2191da177e4SLinus Torvalds|
2201da177e4SLinus Torvalds|
2211da177e4SLinus Torvalds	bsr	round			|round the unnorm based on users
2221da177e4SLinus Torvalds|					;input	a0 ptr to ext X
2231da177e4SLinus Torvalds|					;	d0 g,r,s bits
2241da177e4SLinus Torvalds|					;	d1 PREC/MODE info
2251da177e4SLinus Torvalds|					;output a0 ptr to rounded result
2261da177e4SLinus Torvalds|					;inexact flag set in USER_FPSR
2271da177e4SLinus Torvalds|					;if initial grs set
2281da177e4SLinus Torvalds|
2291da177e4SLinus Torvalds| normalize the rounded result and store value in fp0
2301da177e4SLinus Torvalds|
2311da177e4SLinus Torvalds	bsr	nrm_set			|normalize the unnorm
2321da177e4SLinus Torvalds|					;Input: a0 points to operand to
2331da177e4SLinus Torvalds|					;be normalized
2341da177e4SLinus Torvalds|					;Output: a0 points to normalized
2351da177e4SLinus Torvalds|					;result
2361da177e4SLinus Torvalds	bfclr	LOCAL_SGN(%a0){#0:#8}
2371da177e4SLinus Torvalds	beqs	nrmrndp
2381da177e4SLinus Torvalds	bsetb	#sign_bit,LOCAL_EX(%a0)	|return to IEEE extended format
2391da177e4SLinus Torvaldsnrmrndp:
2401da177e4SLinus Torvalds	fmovel	%fpcr,-(%sp)
2411da177e4SLinus Torvalds	fmovel	#0,%fpcr
2421da177e4SLinus Torvalds	fmovex LOCAL_EX(%a0),%fp0	|move result to fp0
2431da177e4SLinus Torvalds	fmovel	(%sp)+,%fpcr
2441da177e4SLinus Torvalds	rts
2451da177e4SLinus Torvalds
2461da177e4SLinus Torvalds	|end
247