/* * |-----------------------------------------------------------| * | 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: log.s,v 3000.5.1.4 91/08/14 09:31:27 zaineb Exp $ */ /* Algorithm from "Table-driven Implementation of the Logarithm Functions for IEEE Floating-Point Arithmetic", Peter Tang, Argonne National Laboratory, February 2, 1989 Coded in MIPS assembler by Earl Killian. */ #include #include #include #define loge 0.43429448190325182765 #define FSIZE 48 .extern _except1 .text .text$logm .globl log10 .ent log10 log10: .frame sp, 0, ra .prologue 0 li t7, OP_LOG10 j logmain .end log10 .text .text$logm .globl log .ent log log: .frame sp, 0, ra .prologue 0 li t7, OP_LOG j logmain .end log .text .text$logm .ent logmain logmain: subu sp, FSIZE sw ra, FSIZE-4(sp) .frame sp, FSIZE, ra .mask 0x80000000, -4 .prologue 1 /* argument in f12 */ .set noreorder cfc1 t5, $31 /* save FCSR, set round to nearest */ ctc1 $0, $31 /* mode and no exceptions */ and t6, t5, -4 li.d $f10, 1.0644944589178595e+00 // ceil( exp( 1/16)) li.d $f16, 9.3941306281347570e-01 // floor(exp(-1/16)) c.ult.d $f12, $f10 dmfc1 t0, $f12 dsra t1, t0, 32 bc1f 1f srl t2, t1, 20 c.olt.d $f16, $f12 li.d $f10, 0.0 bc1t 5f c.ule.d $f12, $f10 nop bc1t 8f nop beq t2, 0, 4f nop 1: li t4, 2047 beq t2, t4, 7f subu t2, 1023 sll t3, t2, 20 subu t3, t1, t3 dsll t3, t3, 32 dsll t0, t0, 32 dsrl t0, t0, 32 or t3, t3, t0 dmtc1 t3, $f12 .set reorder 2: ctc1 t6, $31 li.d $f16, 3.5184372088832000e+13 // 2^(53-8) mtc1 t2, $f8 add.d $f18, $f12, $f16 la t4, _logtable sub.d $f14, $f18, $f16 dmfc1 t2, $f18 sub.d $f18, $f12, $f14 dsll t2, 32 dsrl t2, 32-4 add.d $f14, $f12 l.d $f10, 128*16+0(t4) // log2head div.d $f18, $f14 cvt.d.w $f8 l.d $f16, 128*16+8(t4) // log2trail mul.d $f0, $f8, $f10 addu t2, t4 l.d $f4, -128*16+0(t2) mul.d $f2, $f8, $f16 add.d $f0, $f4 l.d $f6, -128*16+8(t2) add.d $f18, $f18 li.d $f10, 1.2500053168098584e-02 mul.d $f4, $f18, $f18 add.d $f2, $f6 li.d $f16, 8.3333333333039133e-02 mul.d $f6, $f4, $f10 add.d $f6, $f16 mul.d $f6, $f4 mul.d $f6, $f18 add.d $f6, $f2 add.d $f6, $f18 add.d $f0, $f6 j ret 4: /* denorm */ li.d $f10, 4.4942328371557898e+307 // 2^1022 mul.d $f12, $f10 dmfc1 t0, $f12 dsra t1, t0, 32 dsll t0, t0, 32 dsrl t0, t0, 32 srl t2, t1, 20 subu t2, 1023 sll t3, t2, 20 subu t3, t1, t3 dsll t3, t3, 32 or t3, t3, t0 dmtc1 t3, $f12 addu t2, -1022 b 2b 5: /* exp(-1/16) < x < exp(1/16) */ /* use special approximation */ ctc1 t6, $31 li.d $f10, 1.0 sub.d $f14, $f12, $f10 add.d $f12, $f10 div.d $f12, $f10, $f12 cvt.s.d $f18, $f14 cvt.d.s $f18 sub.d $f8, $f14, $f18 add.d $f2, $f14, $f14 mul.d $f2, $f12 mul.d $f4, $f2, $f2 li.d $f10, 4.3488777770761457e-04 li.d $f16, 2.2321399879194482e-03 mul.d $f6, $f4, $f10 add.d $f6, $f16 li.d $f10, 1.2500000003771751e-02 mul.d $f6, $f4 add.d $f6, $f10 li.d $f16, 8.3333333333331788e-02 mul.d $f6, $f4 add.d $f6, $f16 mul.d $f6, $f4 mul.d $f6, $f2 cvt.s.d $f0, $f2 cvt.d.s $f0 sub.d $f14, $f0 add.d $f14, $f14 mul.d $f18, $f0 sub.d $f14, $f18 mul.d $f8, $f0 sub.d $f14, $f8 mul.d $f14, $f12 add.d $f14, $f6 add.d $f0, $f14 j ret 7: /* log(+Infinity) = +Infinity */ /* log(NaN) = NaN */ mov.d $f0, $f12 j ret 8: /* x <= 0 or x = NaN */ /* is it zero? ($f10 == 0.0) */ c.eq.d $f12, $f10 bc1f 9f li.d $f0, -1.0 // generate -INF li.d $f10, 0.0 div.d $f0, $f10 li t6, FP_Z j set_log_err 9: /* x < 0.0 or x == NaN */ c.eq.d $f12, $f12 bc1f 7b li.d $f0, 0.0 div.d $f0, $f10 // generate a NaN li t6, FP_I set_log_err: move $4, t6 // exception mask move $5, t7 // operation code (funtion name index) dmfc1 $6, $f12 // arg1 dsrl $7, $6, 32 dsll $6, $6, 32 dsrl $6, $6, 32 s.d $f0, 16(sp) // default result xor t5, t5, 0xf80 // inverse exception enable bits sw t5, 24(sp) jal _except1 lw ra, FSIZE-4(sp) addu sp, FSIZE j ra ret: li t6, OP_LOG10 bne t7,t6,retf li.d $f2, loge mul.d $f0, $f2 retf: ctc1 t5, $31 /* restore FCSR */ lw ra, FSIZE-4(sp) addu sp, FSIZE j ra .end logmain