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