/* * |-----------------------------------------------------------| * | Copyright (c) 1991 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 52.227-7013. | * | MIPS Computer Systems, Inc. | * | 950 DeGuigne Drive | * | Sunnyvale, CA 94086 | * |-----------------------------------------------------------| */ /* $Header: llcvt.s,v 3010.2 91/12/10 13:24:31 murphy Exp $ */ #include #ifdef _MIPSEL # define PLSW a0 # define PMSW a1 # define RLSW v0 # define RMSW v1 #else /* _MIPSEB */ # define PMSW a0 # define PLSW a1 # define RMSW v0 # define RLSW v1 #endif /* Convert from 64-bit signed integer to double precision. */ /* double ll_to_d(ll) */ .globl __ll_to_d .ent __ll_to_d __ll_to_d: .frame sp, 0, ra mtc1 PMSW, $f0 mtc1 PLSW, $f2 move t0, PLSW li.d $f8, 4294967296.0 /* 2^32 */ cvt.d.w $f0 cvt.d.w $f2 mul.d $f0, $f8 bgez t0, 12f /* sign bit of LSW was set */ add.d $f2, $f8 /* correct LSW conversion */ 12: add.d $f0, $f2 /* add low part to high */ j ra .end __ll_to_d /* Convert from 64-bit unsigned integer to double precision. */ /* double ull_to_d(ll) */ .globl __ull_to_d .ent __ull_to_d __ull_to_d: .frame sp, 0, ra mtc1 PMSW, $f0 mtc1 PLSW, $f2 move t0, PLSW move t1, PMSW li.d $f8, 4294967296.0 /* 2^32 */ cvt.d.w $f0 cvt.d.w $f2 bgez t1, 12f /* sign bit of MSW was set */ add.d $f0, $f8 /* correct MSW conversion */ 12: mul.d $f0, $f8 bgez t0, 14f /* sign bit of LSW was set */ add.d $f2, $f8 /* correct LSW conversion */ 14: add.d $f0, $f2 /* add low part to high */ j ra .end __ull_to_d /* Convert from 64-bit signed integer to single precision. */ /* float ll_to_f(ll) */ .globl __ll_to_f .ent __ll_to_f __ll_to_f: .frame sp, 0, ra cfc1 t4, $31 /* save FCSR */ ctc1 $0, $31 /* set safe FCSR */ mtc1 PMSW, $f2 mtc1 PLSW, $f4 move t0, PLSW li.d $f8, 4294967296.0 /* 2^32 */ cvt.d.w $f2 cvt.d.w $f4 mul.d $f2, $f8 /* shift up MSW value */ bgez t0, 12f /* sign bit of LSW was set */ add.d $f4, $f8 /* correct LSW convert */ 12: add.d $f0, $f2, $f4 /* add low part to high */ cfc1 t1, $31 /* check for inexact */ and t1, 4 bne t1, 0, 14f /* conversion to double was exact */ ctc1 t4, $31 cvt.s.d $f0 j ra 14: /* conversion to double was not exact, so cvt.s.d would be double round */ li t0, 1 /* mode = round-to-0 */ ctc1 t0, $31 cvt.s.d $f0, $f2 /* move 8 bits from high to low double */ cvt.d.s $f0 sub.d $f6, $f2, $f0 add.d $f4, $f6 mfc1 t2, $f1 /* add value that pushes high 24 bits */ srl t2, 20 /* to low end of double */ addu t2, (53-24) sll t2, 20 mtc1 t2, $f9 mtc1 $0, $f8 ctc1 t4, $31 /* restore FCSR */ add.d $f0, $f8 /* add bias */ add.d $f0, $f4 /* add low part with round to 24 bits of precision */ sub.d $f0, $f8 /* remove bias */ cvt.s.d $f0 j ra .end __ll_to_f /* Convert from 64-bit unsigned integer to single precision. */ /* float ull_to_f(ll) */ .globl __ull_to_f .ent __ull_to_f __ull_to_f: .frame sp, 0, ra cfc1 t4, $31 /* save FCSR */ ctc1 $0, $31 /* set safe FCSR */ mtc1 PMSW, $f2 mtc1 PLSW, $f4 move t0, PLSW move t1, PMSW li.d $f8, 4294967296.0 /* 2^32 */ cvt.d.w $f2 cvt.d.w $f4 bgez t1, 12f /* sign bit of MSW was set */ add.d $f2, $f8 /* correct MSW convert */ 12: mul.d $f2, $f8 /* shift up MSW value */ bgez t0, 14f /* sign bit of LSW was set */ add.d $f4, $f8 /* correct LSW convert */ 14: add.d $f0, $f2, $f4 /* add low part to high */ cfc1 t1, $31 /* check for inexact */ and t1, 4 bne t1, 0, 14f /* conversion to double was exact */ ctc1 t4, $31 cvt.s.d $f0 j ra 14: /* conversion to double was not exact, so cvt.s.d would be double round */ li t0, 1 /* mode = round-to-0 */ ctc1 t0, $31 cvt.s.d $f0, $f2 /* move 8 bits from high to low double */ cvt.d.s $f0 sub.d $f6, $f2, $f0 add.d $f4, $f6 mfc1 t2, $f1 /* add value that pushes high 24 bits */ srl t2, 20 /* to low end of double */ addu t2, (53-24) sll t2, 20 mtc1 t2, $f9 mtc1 $0, $f8 ctc1 t4, $31 /* restore FCSR */ add.d $f0, $f8 /* add bias */ add.d $f0, $f4 /* add low part with round to 24 bits of precision */ sub.d $f0, $f8 /* remove bias */ cvt.s.d $f0 j ra .end __ull_to_f /* Convert from double precision to 64-bit integer. */ /* This is a common routine for signed and unsigned case; * the only difference is the max value, which is passed in $f4. */ /* C rules require truncating the value */ /* longlong dtoll (double); */ .globl __dtoll .ent __dtoll __dtoll: .frame sp, 0, ra cfc1 t6, $31 li t7, 1 /* round to zero (truncate) */ ctc1 t7, $31 mfc1 t8, $f13 li.d $f2, 4.5035996273704960e+15 /* 2^52 */ bltz t8, 10f /* x >= 0 */ c.ult.d $f12, $f2 bc1f 20f /* 0 <= x < 2^52 -- needs rounding */ /* x + 2^52 may be = 2^53 after rounding -- this still works */ add.d $f0, $f12, $f2 /* round */ mfc1 RLSW, $f0 mfc1 RMSW, $f1 subu RMSW, ((52+1023)<<20) b 50f 10: /* x < 0 */ neg.d $f2 c.ult.d $f2, $f12 bc1f 30f /* -2^52 < x < 0 -- needs rounding */ /* x - 2^52 may be = -2^53 after rounding -- this still works */ add.d $f0, $f12, $f2 /* round */ mfc1 RLSW, $f0 mfc1 RMSW, $f1 subu RMSW, ((52+1023+2048)<<20) /* double word negate */ sltu t3, RLSW, 1 negu RLSW not RMSW addu RMSW, t3 b 50f 20: /* x >= 2^52 or NaN */ /* compare against $f4, which is either 2^63-1 or 2^64-1 */ mfc1 RLSW, $f12 mfc1 t1, $f13 c.ult.d $f12, $f4 bc1f 40f /* 2^52 <= x < 2^63/4 */ li t2, (1<<20) /* hidden bit in high word */ subu t3, t2, 1 /* mask for high word */ and RMSW, t1, t3 /* mask out exponent */ or RMSW, t2 /* add back hidden bit */ srl t0, t1, 20 /* shift = exponent - (52+bias) */ subu t0, 1023+52 /* ... */ negu t4, t0 /* high |= low >> (32-shift) */ srl t5, RLSW, t4 /* ... */ sll RMSW, t0 /* high <<= shift */ sll RLSW, t0 /* low <<= shift */ beq t0, 0, 50f /* if shift = 0, that's all */ or RMSW, t5 /* else add bits shifted out of low */ b 50f 30: /* x <= -2^52 or NaN */ li.d $f2, -9.2233720368547758e+18 /* -2^63 */ mfc1 RLSW, $f12 mfc1 t1, $f13 c.ule.d $f2, $f12 bc1f 40f /* -2^63 <= x <= -2^52 */ li t2, (1<<20) /* hidden bit in high word */ subu t3, t2, 1 /* mask for high word */ and RMSW, t1, t3 /* mask out exponent */ or RMSW, t2 /* add back hidden bit */ srl t0, t1, 20 /* shift = exponent - (52+bias) */ subu t0, 52+1023+2048 /* ... */ negu t4, t0 /* high |= low >> (32-shift) */ srl t5, RLSW, t4 /* ... */ sll RMSW, t0 /* high <<= shift */ sll RLSW, t0 /* low <<= shift */ beq t0, 0, 32f /* if shift = 0, that's all */ or RMSW, t5 /* else add bits shifted out of low */ 32: /* double word negate */ sltu t3, RLSW, 1 negu RLSW not RMSW addu RMSW, t3 b 50f 40: /* x is NaN or x < -2^63 or x >= 2^63/4 */ /* raise Invalid */ li RMSW, 0x7fffffff /* signed case */ li RLSW, 0xffffffff li.d $f2, 9.223372036854775807e+18 /* 2^63-1 */ c.ueq.d $f2, $f4 bc1t 42f li RMSW, 0xffffffff /* unsigned case */ 42: cfc1 t0, $31 or t0, ((1<<12)|(1<<2)) ctc1 t0, $31 b 50f 50: cfc1 t7, $31 and t7, -4 or t6, t7 ctc1 t6, $31 j ra .end __dtoll /* Convert from double precision to 64-bit signed integer. */ /* C rules require truncating the value */ /* longlong d_to_ll (double); */ .globl __d_to_ll .ent __d_to_ll __d_to_ll: subu sp, 32 sw ra, 28(sp) .mask 0x80000000, -4 .frame sp, 32, ra li.d $f4, 9.223372036854775807e+18 /* 2^63-1 */ jal __dtoll /* use v0,v1 that are already set */ lw ra, 28(sp) addu sp, 32 j ra .end __d_to_ll /* longlong f_to_ll (float) */ .globl __f_to_ll .ent __f_to_ll __f_to_ll: subu sp, 32 sw ra, 28(sp) .mask 0x80000000, -4 .frame sp, 32, ra cvt.d.s $f12, $f12 jal __d_to_ll /* use v0,v1 that are already set */ lw ra, 28(sp) addu sp, 32 j ra .end __f_to_ll /* Convert from double precision to 64-bit unsigned integer. */ /* C rules require truncating the value */ /* ulonglong d_to_ull (double); */ .globl __d_to_ull .ent __d_to_ull __d_to_ull: subu sp, 32 sw ra, 28(sp) .mask 0x80000000, -4 .frame sp, 32, ra li.d $f4, 1.8446744073709551615e+19 /* 2^64-1 */ jal __dtoll /* use v0,v1 that are already set */ lw ra, 28(sp) addu sp, 32 j ra .end __d_to_ull /* ulonglong f_to_ull (float) */ .globl __f_to_ull .ent __f_to_ull __f_to_ull: subu sp, 32 sw ra, 28(sp) .mask 0x80000000, -4 .frame sp, 32, ra cvt.d.s $f12, $f12 jal __d_to_ull /* use v0,v1 that are already set */ lw ra, 28(sp) addu sp, 32 j ra .end __f_to_ull