Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

188 lines
4.8 KiB

/*
* |-----------------------------------------------------------|
* | Copyright (c) 1991, 1990 MIPS Computer Systems, Inc. |
* | All Rights Reserved |
* |-----------------------------------------------------------|
* | Restricted Rights Legend |
* | Use, duplication, or disclosure by the Government is |
* | subject to restrictions as set forth in |
* | subparagraph (c)(1)(ii) of the Rights in Technical |
* | Data and Computer Software Clause of DFARS 252.227-7013. |
* | MIPS Computer Systems, Inc. |
* | 950 DeGuigne Avenue |
* | Sunnyvale, California 94088-3650, USA |
* |-----------------------------------------------------------|
*/
/* $Header: exp.s,v 3000.5.1.7 92/01/29 15:51:28 zaineb Exp $ */
/* Algorithm from
"Table-driven Implementation of the Exponential Function for
IEEE Floating Point", Peter Tang, Argonne National Laboratory,
December 3, 1987
as implemented in C by M. Mueller, April 20 1988, Evans & Sutherland.
Coded in MIPS assembler by Earl Killian.
*/
.globl exp
.extern _exptable
#include <kxmips.h>
#include <trans.h>
#include <fpieee.h>
#ifdef CRTDLL
.extern _HUGE_dll
#define _HUGE _HUGE_dll
#else
.extern _HUGE
#endif
.text
.ent exp
.extern errno 4
#define ERANGE 34
exp:
.frame sp, 0, ra
.prologue 0
/* argument in f12 */
.set noreorder
li.d $f10, 709.78271289338397 // expmax
cfc1 t4, $31 // read fp control/status
c.ole.d $f12, $f10 // check if special
li.d $f14, -744.44007192138122 // expmin
bc1f 90f // if NaN, +Infinity,
// or greater than expmax
c.lt.d $f12, $f14 // check for exp(x) = 0
li t1, -4
bc1t 80f // if less than expmin
and t1, t4 // rounding mode = nearest
.set reorder
ctc1 t1, $31 // write fp control/status
// argument reduction
li.d $f10, 46.166241308446828
mul.d $f2, $f12, $f10
li.d $f14, 2.1660849390173098e-2
li.d $f10, -2.325192846878874e-12
cvt.w.d $f2
mfc1 t0, $f2
and t1, t0, 31 // region
sra t2, t0, 5 // scale
cvt.d.w $f2
mul.d $f4, $f2, $f14
mul.d $f6, $f2, $f10
sub.d $f4, $f12, $f4
add.d $f2, $f4, $f6
li.d $f10, 1.3888949086377719e-3
li.d $f14, 8.3333679843421958e-3
mul.d $f8, $f2, $f10
add.d $f0, $f8, $f14
li.d $f10, 4.1666666666226079e-2
li.d $f14, 1.6666666666526087e-1
mul.d $f0, $f2
add.d $f0, $f10
mul.d $f0, $f2
add.d $f0, $f14
li.d $f10, 0.5
mul.d $f0, $f2
add.d $f0, $f10
mul.d $f0, $f2
mul.d $f0, $f2
add.d $f0, $f6
add.d $f0, $f4
sll t1, 4
la t1, _exptable(t1)
l.d $f10, 0(t1)
l.d $f14, 8(t1)
add.d $f8, $f10, $f14
mul.d $f0, $f8
add.d $f0, $f14
add.d $f0, $f10
beq t2, 0, 60f // early out for 0 scale
mfc1 t0, $f1 // get result high word
ctc1 t4, $31 // restore control/status
sll t1, t0, 1 // extract exponent
srl t1, 20+1 // ...
addu t1, t2 // add scale to check for denorm
sll t2, 20
blez t1, 70f
addu t0, t2 // add scale
mtc1 t0, $f1 // put back in result high word
j ra
60: // scale = 0, just restore control/status and return
ctc1 t4, $31
j ra
70: // denorm result
addu t2, 64<<20
addu t0, t2
mtc1 t0, $f1
li.d $f2, 5.4210108624275222e-20
mul.d $f0, $f2
j ra
80: // argument < expmin
li.d $f0, 0.0 // should raise underflow
j set_uflow_err
j ra
90: // raise Overflow and return +Infinity
mfc1 t0, $f13 // extract argument exponent
sll t0, 1
srl t0, 20+1
beq t0, 2047, 91f // if NaN or Infinity
li.d $f0, 0.898846567431158e308
add.d $f0, $f0 // raise Overflow
91:
j set_oflow_err
.end exp
.extern _except1
.ent set_uflow_err
set_uflow_err:
#define FSIZE 48
.frame sp, FSIZE, ra
.mask 0x80000000, -4
subu sp, FSIZE
sw ra, FSIZE-4(sp)
.prologue 1
li $4, (FP_U | FP_P) // exception mask
li $5, OP_EXP // operation code (funtion name index)
mfc1.d $6, $f12 // arg1
li.d $f0, 0.0 // api help says return zero for overflow
s.d $f0, 16(sp) // default result
cfc1 t7, $31 // floating point control/status register
xor t7, t7, 0xf80 // inverse exception enable bits
sw t7, 24(sp)
jal _except1
lw ra, FSIZE-4(sp)
addu sp, FSIZE
j ra
#undef FSIZE
.end set_uflow_err
.ent set_oflow_err
set_oflow_err:
#define FSIZE 48
.frame sp, FSIZE, ra
.mask 0x80000000, -4
subu sp, FSIZE
sw ra, FSIZE-4(sp)
.prologue 1
li $4, (FP_O | FP_P) // exception mask
li $5, OP_EXP // operation code (funtion name index)
mfc1.d $6, $f12 // arg1
l.d $f0, _HUGE // api help says return HUGE_VAL for overflow
s.d $f0, 16(sp) // default result
cfc1 t7, $31 // floating point control/status register
xor t7, t7, 0xf80 // inverse exception enable bits
sw t7, 24(sp)
jal _except1
lw ra, FSIZE-4(sp)
addu sp, FSIZE
j ra
#undef FSIZE
.end set_oflow_err