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.
 
 
 
 
 
 

332 lines
7.2 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: fmod.s,v 3000.3.1.6 91/10/09 11:14:56 zaineb Exp $ */
.extern _except2
.extern errno 4
#include <kxmips.h>
#include <trans.h>
#include <fpieee.h>
/* double fmod(double x, double y) */
.text .text$fmodm
.ent fmod_small
fmod_small:
.frame sp, 16, ra
.mask 0x80000000, 0
/* y is almost subnormal */
/* f0 = |x|, f2 = |y|, t0 = sign of x, t2 = 2047<<20,
t3 = fcsr, fcsr = round-to-zero */
/* scale both x and y, compute remainder, and unscale it */
subu sp, 16
sw ra, 16(sp)
.prologue 1
li.d $f18, 1.2474001934591999e+291 /* 2^(1024-57) */
li.d $f16, 1.4411518807585587e+17 /* 2^57 */
c.lt.d $f0, $f18
mul.d $f2, $f16
bc1t 10f
/* x * 2^57 would overflow */
/* first compute with unscaled x to chop it down to size */
li t0, 0
bal fmod1
li t4, 1
ctc1 t4, $31
mfc1 t0, $f13
li.d $f16, 1.4411518807585587e+17 /* 2^57 */
mul.d $f0, $f16
bal fmod2
b 20f
10: mul.d $f0, $f16
bal fmod1
20: li.d $f16, 6.9388939039072284e-18 /* 2^-57 */
mul.d $f0, $f16
lw ra, 16(sp)
addu sp, 16
j ra
.end fmod_small
.text .text$fmodm
.globl fmod
.ent fmod
fmod:
.frame sp, 0, ra
.prologue 0
.set noreorder
c.un.d $f12, $f14 /* x NaN or y NaN? */
mfc1 t0, $f13 /* sign and exponent of x */
mfc1 t1, $f15 /* sign and exponent of y */
bc1t 70f
cfc1 t3, $31 /* t3 = fcsr */
abs.d $f0, $f12 /* f0 = |x| */
abs.d $f2, $f14 /* f2 = |y| */
li t2, (2047<<20)
c.lt.d $f0, $f2
and t8, t0, t2 /* check for x = +-Infinity */
and t9, t1, t2
bc1t 30f
li t4, 1
beq t8, t2, 80f
ctc1 t4, $31 /* set round to zero mode */
beq t9, 0, 90f /* y is 0 or subnormal */
li t8, 0x03900000
bleu t9, t8, fmod_small /* almost subnormals */
nop
fmod1: /* entry from fmod_subnormal, fmod_small, and fmodf_punt */
/* f0 = |x|, f2 = |y|, t0 = sign of x, t2 = 2047<<20,
t3 = fcsr, fcsr = round-to-zero */
20: /* x > y */
div.d $f8, $f0, $f2 /* q = x/y (>= 1.0) */
mfc1 t8, $f2 /* f4 = y with low 27 bits 0 */
mfc1 t4, $f1
mfc1 t5, $f3
mov.d $f4, $f2
srl t8, 27
sll t8, 27
mtc1 t8, $f4
and t4, t2
and t5, t2
subu t4, t5
subu t4, (25<<20)
bgtz t4, 40f
sub.d $f6, $f2, $f4 /* f6 = low 27 bits of y */
22: /* q < 2^26 */
cvt.w.d $f16, $f8 /* truncate */
cvt.d.w $f8, $f16
mul.d $f4, $f8 /* exact (26 x 26 = 52 bits) */
mul.d $f6, $f8 /* exact (27 x 26 = 53 bits) */
sub.d $f0, $f4 /* exact */
sub.d $f0, $f6 /* exact */
fmod2: /* entry from fmod_subnormal and fmod_small */
c.lt.d $f0, $f2
nop
bc1f 20b
nop
.set reorder
30: /* x < y */
/* negate remainder if dividend was negative */
bgez t0, 36f
neg.d $f0
36: ctc1 t3, $31
j ra
40: /* q >= 2^26 */
mfc1 t8, $f3
mfc1 t9, $f5
mov.d $f10, $f2
addu t8, t4
addu t9, t4
mtc1 t8, $f11
mtc1 t9, $f5
div.d $f8, $f0, $f10
sub.d $f6, $f10, $f4
b 22b
70: /* x NaN or y NaN */
c.eq.d $f12, $f12
bc1t 72f
mov.d $f0, $f12
j ra
72: mov.d $f0, $f14
j ra
80: /* x = +-Infinity */
ctc1 t3, $31
sub.d $f0, $f12, $f12 /* raise Invalid, return NaN */
j ra
90: /* y is zero or subnormal */
mfc1 t8, $f14
sll t9, t1, 1
bne t9, 0, fmod_subnormal
bne t8, 0, fmod_subnormal
/* y = +-0 */
ctc1 t3, $31
div.d $f0, $f14, $f14 /* raise Invalid, return NaN */
j set_fmod_err
.end fmod
.text .text$fmodm
.ent fmod_subnormal
fmod_subnormal:
.frame sp, 16, ra
.mask 0x80000000, 0
/* y is subnormal */
/* f0 = |x|, f2 = |y|, t0 = sign of x, t2 = 2047<<20,
t3 = fcsr, fcsr = round-to-zero */
/* scale both x and y, compute remainder, and unscale it */
subu sp, 16
sw ra, 16(sp)
.prologue 1
li.d $f18, 8.6555775981267394e+273 /* 2^(1024-114) */
li.d $f16, 2.0769187434139311e+34 /* 2^114 */
c.lt.d $f0, $f18
mul.d $f2, $f16
bc1t 10f
/* x * 2^114 would overflow */
/* first compute with unscaled x to chop it down to size */
li t0, 0
bal fmod1
li t4, 1
ctc1 t4, $31
mfc1 t0, $f13
li.d $f16, 2.0769187434139311e+34 /* 2^114 */
mul.d $f0, $f16
bal fmod2
b 20f
10: mul.d $f0, $f16
bal fmod1
20: li.d $f16, 4.8148248609680896e-35 /* 2^-114 */
mul.d $f0, $f16
lw ra, 16(sp)
addu sp, 16
j ra
.end fmod_subnormal
/* float fmodf(float x, float y) */
.text .text$fmodm
.globl fmodf
.ent fmodf
fmodf:
.frame sp, 0, ra
.prologue 0
.set noreorder
c.un.s $f12, $f14 /* x NaN or y NaN? */
mfc1 t0, $f12 /* sign and exponent of x */
mfc1 t1, $f14 /* sign and exponent of y */
bc1t 70f
cfc1 t3, $31 /* t3 = fcsr */
abs.s $f0, $f12 /* f0 = |x| */
abs.s $f2, $f14 /* f2 = |y| */
li t2, (255<<23)
c.lt.s $f0, $f2
and t8, t0, t2 /* check for x = +-Infinity */
and t9, t1, t2
bc1t 30f
li t4, 1
beq t8, t2, 80f
ctc1 t4, $31 /* set round to zero mode */
beq t9, 0, 90f /* y is 0 or subnormal */
cvt.d.s $f4, $f2
.set reorder
20: /* x > y */
div.s $f8, $f0, $f2 /* q = x/y (>= 1.0) */
mfc1 t4, $f0
mfc1 t5, $f2
and t4, t2
and t5, t2
subu t4, t5
subu t4, (23<<23)
bgtz t4, fmodf_punt
/* q < 2^24 */
cvt.w.s $f16, $f8 /* truncate */
cvt.d.w $f8, $f16
mul.d $f8, $f4
cvt.d.s $f0
sub.d $f0, $f8
c.lt.s $f0, $f4
cvt.s.d $f0
bc1f 20b
30: /* x < y */
/* negate remainder if dividend was negative */
bgez t0, 36f
neg.s $f0
36: ctc1 t3, $31
j ra
70: /* x NaN or y NaN */
c.eq.s $f12, $f12
bc1t 72f
mov.s $f0, $f12
j ra
72: mov.s $f0, $f14
j ra
80: /* x = +-Infinity */
ctc1 t3, $31
sub.s $f0, $f12, $f12 /* raise Invalid, return NaN */
mov.s $f0,$f12
j ra
90: /* y is zero or subnormal */
sll t9, t1, 1
bne t9, 0, fmodf_punt
/* y = +-0 */
ctc1 t3, $31
div.s $f0, $f14, $f14 /* raise Invalid, return NaN */
j ra
.end fmodf
.text .text$fmodm
.ent fmodf_punt
fmodf_punt:
.frame sp, 16, ra
.mask 0x80000000, 0
/* f0 = |x|, f2 = |y|, t0 = sign of x,
t3 = fcsr, fcsr = round-to-zero */
subu sp, 16
sw ra, 16(sp)
.prologue 1
cvt.d.s $f12
cvt.d.s $f14
li t2, (2047<<20)
bal fmod1
cvt.s.d $f0
lw ra, 16(sp)
addu sp, 16
j ra
.end fmodf_punt
.text .text$fmodm
.ent set_fmod_err
set_fmod_err:
#define FSIZE 48
.frame sp, FSIZE, ra
.mask 0x80000000, -4
subu sp, FSIZE
sw ra, FSIZE-4(sp)
.prologue 1
li $4, FP_I // exception mask
li $5, OP_FMOD // operation code (funtion name index)
mfc1.d $6, $f12 // arg1
s.d $f14, 16(sp) // arg2 (TODO: pass 0.0 as arg2???, see above)
s.d $f0, 24(sp) // default result
cfc1 t7, $31 // floating point control/status register
xor t7, t7, 0xf80 // inverse exception enable bits
sw t7, 32(sp)
jal _except2
lw ra, FSIZE-4(sp)
addu sp, FSIZE
j ra
#undef FSIZE
.end set_fmod_err