xref: /csrg-svn/lib/libc/mips/gen/ldexp.s (revision 61141)
152706Sbostic/*-
2*61141Sbostic * Copyright (c) 1991, 1993
3*61141Sbostic *	The Regents of the University of California.  All rights reserved.
452706Sbostic *
552706Sbostic * This code is derived from software contributed to Berkeley by
652706Sbostic * Ralph Campbell.
752706Sbostic *
852706Sbostic * %sccs.include.redist.c%
952706Sbostic */
1052706Sbostic
1155705Sralph#include <machine/machAsmDefs.h>
1252739Sbostic
1352706Sbostic#if defined(LIBC_SCCS) && !defined(lint)
14*61141Sbostic	ASMSTR("@(#)ldexp.s	8.1 (Berkeley) 06/04/93")
1552706Sbostic#endif /* LIBC_SCCS and not lint */
1652706Sbostic
1752855Sralph#define DEXP_INF	0x7ff
1852855Sralph#define DEXP_BIAS	1023
1952855Sralph#define DEXP_MIN	-1022
2052855Sralph#define DEXP_MAX	1023
2152855Sralph#define DFRAC_BITS	52
2252855Sralph#define DIMPL_ONE	0x00100000
2352855Sralph#define DLEAD_ZEROS	31 - 20
2452855Sralph#define STICKYBIT	1
2552855Sralph#define GUARDBIT	0x80000000
2652855Sralph#define DSIGNAL_NAN	0x00040000
2752855Sralph#define DQUIET_NAN0	0x0007ffff
2852855Sralph#define DQUIET_NAN1	0xffffffff
2952706Sbostic
3052706Sbostic/*
3152855Sralph * double ldexp(x, N)
3252855Sralph *	double x; int N;
3352855Sralph *
3452855Sralph * Return x * (2**N), for integer values N.
3552706Sbostic */
3652706SbosticLEAF(ldexp)
3752855Sralph	mfc1	v1, $f13		# get MSW of x
3852855Sralph	mfc1	t3, $f12		# get LSW of x
3952855Sralph	sll	t1, v1, 1		# get x exponent
4052855Sralph	srl	t1, t1, 32 - 11
4152855Sralph	beq	t1, DEXP_INF, 9f	# is it a NAN or infinity?
4252855Sralph	beq	t1, zero, 1f		# zero or denormalized number?
4352855Sralph	addu	t1, t1, a2		# scale exponent
4452855Sralph	sll	v0, a2, 20		# position N for addition
4552855Sralph	bge	t1, DEXP_INF, 8f	# overflow?
4652855Sralph	addu	v0, v0, v1		# multiply by (2**N)
4752855Sralph	ble	t1, zero, 4f		# underflow?
4852855Sralph	mtc1	v0, $f1			# save MSW of result
4952855Sralph	mtc1	t3, $f0			# save LSW of result
5052855Sralph	j	ra
5152706Sbostic1:
5252855Sralph	sll	t2, v1, 32 - 20		# get x fraction
5352855Sralph	srl	t2, t2, 32 - 20
5452855Sralph	srl	t0, v1, 31		# get x sign
5552855Sralph	bne	t2, zero, 1f
5652855Sralph	beq	t3, zero, 9f		# result is zero
5752855Sralph1:
5852855Sralph/*
5952855Sralph * Find out how many leading zero bits are in t2,t3 and put in t9.
6052855Sralph */
6152855Sralph	move	v0, t2
6252855Sralph	move	t9, zero
6352855Sralph	bne	t2, zero, 1f
6452855Sralph	move	v0, t3
6552855Sralph	addu	t9, 32
6652855Sralph1:
6752855Sralph	srl	t4, v0, 16
6852855Sralph	bne	t4, zero, 1f
6952855Sralph	addu	t9, 16
7052855Sralph	sll	v0, 16
7152855Sralph1:
7252855Sralph	srl	t4, v0, 24
7352855Sralph	bne	t4, zero, 1f
7452855Sralph	addu	t9, 8
7552855Sralph	sll	v0, 8
7652855Sralph1:
7752855Sralph	srl	t4, v0, 28
7852855Sralph	bne	t4, zero, 1f
7952855Sralph	addu	t9, 4
8052855Sralph	sll	v0, 4
8152855Sralph1:
8252855Sralph	srl	t4, v0, 30
8352855Sralph	bne	t4, zero, 1f
8452855Sralph	addu	t9, 2
8552855Sralph	sll	v0, 2
8652855Sralph1:
8752855Sralph	srl	t4, v0, 31
8852855Sralph	bne	t4, zero, 1f
8952855Sralph	addu	t9, 1
9052855Sralph/*
9152855Sralph * Now shift t2,t3 the correct number of bits.
9252855Sralph */
9352855Sralph1:
9457856Sralph	subu	t9, t9, DLEAD_ZEROS	# dont count normal leading zeros
9552855Sralph	li	t1, DEXP_MIN + DEXP_BIAS
9652855Sralph	subu	t1, t1, t9		# adjust exponent
9752855Sralph	addu	t1, t1, a2		# scale exponent
9852855Sralph	li	v0, 32
9952855Sralph	blt	t9, v0, 1f
10052855Sralph	subu	t9, t9, v0		# shift fraction left >= 32 bits
10152855Sralph	sll	t2, t3, t9
10252855Sralph	move	t3, zero
10352855Sralph	b	2f
10452855Sralph1:
10552855Sralph	subu	v0, v0, t9		# shift fraction left < 32 bits
10652855Sralph	sll	t2, t2, t9
10752855Sralph	srl	t4, t3, v0
10852855Sralph	or	t2, t2, t4
10952855Sralph	sll	t3, t3, t9
11052855Sralph2:
11152855Sralph	bge	t1, DEXP_INF, 8f	# overflow?
11252855Sralph	ble	t1, zero, 4f		# underflow?
11352855Sralph	sll	t2, t2, 32 - 20		# clear implied one bit
11452855Sralph	srl	t2, t2, 32 - 20
11552855Sralph3:
11652855Sralph	sll	t1, t1, 31 - 11		# reposition exponent
11752855Sralph	sll	t0, t0, 31		# reposition sign
11852855Sralph	or	t0, t0, t1		# put result back together
11952855Sralph	or	t0, t0, t2
12052855Sralph	mtc1	t0, $f1			# save MSW of result
12152855Sralph	mtc1	t3, $f0			# save LSW of result
12252706Sbostic	j	ra
12352855Sralph4:
12452855Sralph	li	v0, 0x80000000
12552855Sralph	ble	t1, -52, 7f		# is result too small for denorm?
12652855Sralph	sll	t2, v1, 31 - 20		# clear exponent, extract fraction
12752855Sralph	or	t2, t2, v0		# set implied one bit
12852855Sralph	blt	t1, -30, 2f		# will all bits in t3 be shifted out?
12952855Sralph	srl	t2, t2, 31 - 20		# shift fraction back to normal position
13052855Sralph	subu	t1, t1, 1
13152855Sralph	sll	t4, t2, t1		# shift right t2,t3 based on exponent
13252855Sralph	srl	t8, t3, t1		# save bits shifted out
13352855Sralph	negu	t1
13452855Sralph	srl	t3, t3, t1
13552855Sralph	or	t3, t3, t4
13652855Sralph	srl	t2, t2, t1
13752855Sralph	bge	t8, zero, 1f		# does result need to be rounded?
13852855Sralph	addu	t3, t3, 1		# round result
13952855Sralph	sltu	t4, t3, 1
14052855Sralph	sll	t8, t8, 1
14152855Sralph	addu	t2, t2, t4
14252855Sralph	bne	t8, zero, 1f		# round result to nearest
14352855Sralph	and	t3, t3, ~1
14452855Sralph1:
14552855Sralph	mtc1	t3, $f0			# save denormalized result (LSW)
14652855Sralph	mtc1	t2, $f1			# save denormalized result (MSW)
14752855Sralph	bge	v1, zero, 1f		# should result be negative?
14852855Sralph	neg.d	$f0, $f0		# negate result
14952855Sralph1:
15052855Sralph	j	ra
15152706Sbostic2:
15252855Sralph	mtc1	zero, $f1		# exponent and upper fraction
15352855Sralph	addu	t1, t1, 20		# compute amount to shift right by
15452855Sralph	sll	t8, t2, t1		# save bits shifted out
15552855Sralph	negu	t1
15652855Sralph	srl	t3, t2, t1
15752855Sralph	bge	t8, zero, 1f		# does result need to be rounded?
15852855Sralph	addu	t3, t3, 1		# round result
15952855Sralph	sltu	t4, t3, 1
16052855Sralph	sll	t8, t8, 1
16152855Sralph	mtc1	t4, $f1			# exponent and upper fraction
16252855Sralph	bne	t8, zero, 1f		# round result to nearest
16352855Sralph	and	t3, t3, ~1
16452855Sralph1:
16552855Sralph	mtc1	t3, $f0
16652855Sralph	bge	v1, zero, 1f		# is result negative?
16752855Sralph	neg.d	$f0, $f0		# negate result
16852855Sralph1:
16952706Sbostic	j	ra
17052706Sbostic7:
17152855Sralph	mtc1	zero, $f0		# result is zero
17252706Sbostic	mtc1	zero, $f1
17352855Sralph	beq	t0, zero, 1f		# is result positive?
17452855Sralph	neg.d	$f0, $f0		# negate result
17552855Sralph1:
17652855Sralph	j	ra
17752706Sbostic8:
17852855Sralph	li	t1, 0x7ff00000		# result is infinity (MSW)
17952855Sralph	mtc1	t1, $f1
18052855Sralph	mtc1	zero, $f0		# result is infinity (LSW)
18152855Sralph	bge	v1, zero, 1f		# should result be negative infinity?
18252855Sralph	neg.d	$f0, $f0		# result is negative infinity
18352855Sralph1:
18452855Sralph	add.d	$f0, $f0		# cause overflow faults if enabled
18552706Sbostic	j	ra
18652706Sbostic9:
18752855Sralph	mov.d	$f0, $f12		# yes, result is just x
18852706Sbostic	j	ra
18952706SbosticEND(ldexp)
190