diff options
Diffstat (limited to 'private/crt32/helper')
-rw-r--r-- | private/crt32/helper/empty.c | 5 | ||||
-rw-r--r-- | private/crt32/helper/makefile | 8 | ||||
-rw-r--r-- | private/crt32/helper/mips/llabsdiv.c | 62 | ||||
-rw-r--r-- | private/crt32/helper/mips/llbit.c | 127 | ||||
-rw-r--r-- | private/crt32/helper/mips/llcvt.s | 364 | ||||
-rw-r--r-- | private/crt32/helper/mips/lldefs.h | 92 | ||||
-rw-r--r-- | private/crt32/helper/mips/lldiv.c | 251 | ||||
-rw-r--r-- | private/crt32/helper/mips/lldivrem.s | 237 | ||||
-rw-r--r-- | private/crt32/helper/mips/llmul.s | 57 | ||||
-rw-r--r-- | private/crt32/helper/mips/llshift.s | 226 | ||||
-rw-r--r-- | private/crt32/helper/mips/llshiftt.c | 146 | ||||
-rw-r--r-- | private/crt32/helper/sources | 65 |
12 files changed, 1640 insertions, 0 deletions
diff --git a/private/crt32/helper/empty.c b/private/crt32/helper/empty.c new file mode 100644 index 000000000..b93113c48 --- /dev/null +++ b/private/crt32/helper/empty.c @@ -0,0 +1,5 @@ +// +// This empty file is here to force build to make this directory. +// + + diff --git a/private/crt32/helper/makefile b/private/crt32/helper/makefile new file mode 100644 index 000000000..aa4bbc1a6 --- /dev/null +++ b/private/crt32/helper/makefile @@ -0,0 +1,8 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def + + diff --git a/private/crt32/helper/mips/llabsdiv.c b/private/crt32/helper/mips/llabsdiv.c new file mode 100644 index 000000000..3a00d9143 --- /dev/null +++ b/private/crt32/helper/mips/llabsdiv.c @@ -0,0 +1,62 @@ +/* + * |-----------------------------------------------------------| + * | 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 | + * |-----------------------------------------------------------| + */ +#ident "$Header: llabsdiv.c,v 3010.1 92/05/15 17:22:16 murphy Exp $" +/* Copyright (c) 1988 AT&T */ +/* All Rights Reserved */ + +/* This is loosely based on: */ +/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ +/* The copyright notice above does not evidence any */ +/* actual or intended publication of such source code. */ + +/*LINTLIBRARY*/ +#include <stdlib.h> +#include "lldefs.h" + +typedef struct { + long_long quot; + long_long rem; +} lldiv_t; + +/* ANSI 4.10.6.1 */ +long_long +llabs(arg) +long_long arg; +{ + return (arg >= 0 ? arg : -arg); +} + +/* ANSI 4.10.6.2 */ +lldiv_t lldiv(numer, denom) +long_long numer; +long_long denom; +{ + lldiv_t sd; + + if (numer >= 0 && denom < 0) { + numer = -numer; + sd.quot = -(numer / denom); + sd.rem = -(numer % denom); + } else if (numer < 0 && denom > 0) { + denom = -denom; + sd.quot = -(numer / denom); + sd.rem = numer % denom; + } else { + sd.quot = numer / denom; + sd.rem = numer % denom; + } + return(sd); +} diff --git a/private/crt32/helper/mips/llbit.c b/private/crt32/helper/mips/llbit.c new file mode 100644 index 000000000..e79a2c662 --- /dev/null +++ b/private/crt32/helper/mips/llbit.c @@ -0,0 +1,127 @@ +/* + * |-----------------------------------------------------------| + * | 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: llbit.c,v 3010.2 91/12/20 10:24:03 murphy Exp $ */ + +#include <limits.h> +#define BITS_PER_LONGLONG 64 +#include "lldefs.h" + +/* Disable bit shift intrinsics so this code will work properly. */ +#pragma function(__ll_lshift) +#pragma function(__ll_rshift) +#pragma function(__ull_rshift) + +extern ulonglong_t +__ull_bit_extract (ulonglong_t *addr, unsigned start_bit, unsigned length) +{ + /* assume 32 < length < 64 */ + + unsigned words = start_bit / BITS_PER_LONGLONG; + unsigned lbits = start_bit % BITS_PER_LONGLONG; + unsigned rbits = BITS_PER_LONGLONG - (lbits + length); + llvalue llval, addrval, mask, one; + + addr += words; + addrval.ull = *addr; + SET_LL(one, 1); + SET_LL(mask, 1); + mask.ull = __ll_lshift(mask.ull, length); + LL_SUB(mask, mask, one); + mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */ + LL_AND(llval, addrval, mask); + llval.ull = __ull_rshift(llval.ull, lbits+rbits); + return llval.ull; +} + +extern ulonglong_t +__ull_bit_insert (ulonglong_t *addr, unsigned start_bit, unsigned length, ulonglong_t val) +{ + /* assume 32 < length < 64 */ + + unsigned words = start_bit / BITS_PER_LONGLONG; + unsigned lbits = start_bit % BITS_PER_LONGLONG; + unsigned rbits = BITS_PER_LONGLONG - (lbits + length); + llvalue llval, addrval, mask, nmask, one; + + addr += words; + llval.ull = val; + addrval.ull = *addr; + SET_LL(one, 1); + SET_LL(mask, 1); + mask.ull = __ll_lshift(mask.ull, length); + LL_SUB(mask, mask, one); + mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */ + LL_NOT(nmask, mask); + LL_AND(addrval, addrval, nmask); /* clear the field */ + llval.ull = __ll_lshift(llval.ull, lbits+rbits);/* clear lhs, rhs */ + llval.ull = __ull_rshift(llval.ull, rbits); + LL_OR(addrval, addrval, llval); + *addr = addrval.ull; + llval.ull = __ull_rshift(llval.ull, lbits); /* truncated val */ + return llval.ull; +} + +extern longlong_t +__ll_bit_extract (ulonglong_t *addr, unsigned start_bit, unsigned length) +{ + /* assume 32 < length < 64 */ + + unsigned words = start_bit / BITS_PER_LONGLONG; + unsigned lbits = start_bit % BITS_PER_LONGLONG; + unsigned rbits = BITS_PER_LONGLONG - (lbits + length); + llvalue llval, addrval, mask, one; + + addr += words; + addrval.ull = *addr; + SET_LL(one, 1); + SET_LL(mask, 1); + mask.ull = __ll_lshift(mask.ull, length); + LL_SUB(mask, mask, one); + mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */ + LL_AND(llval, addrval, mask); + llval.ull = __ll_lshift(llval.ull, rbits); + llval.ull = __ll_rshift(llval.ull, lbits+rbits); + return llval.ull; +} + +extern longlong_t +__ll_bit_insert (ulonglong_t *addr,unsigned start_bit, unsigned length, longlong_t val) +{ + /* assume 32 < length < 64 */ + + unsigned words = start_bit / BITS_PER_LONGLONG; + unsigned lbits = start_bit % BITS_PER_LONGLONG; + unsigned rbits = BITS_PER_LONGLONG - (lbits + length); + llvalue llval, addrval, mask, nmask, one; + + addr += words; + llval.ull = val; + addrval.ull = *addr; + SET_LL(one, 1); + SET_LL(mask, 1); + mask.ull = __ll_lshift(mask.ull, length); + LL_SUB(mask, mask, one); + mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */ + LL_NOT(nmask, mask); + LL_AND(addrval, addrval, nmask); /* clear the field */ + llval.ull = __ll_lshift(llval.ull, lbits+rbits);/* clear lhs, rhs */ + llval.ull = __ull_rshift(llval.ull, rbits); + LL_OR(addrval, addrval, llval); + *addr = addrval.ull; + llval.ull = __ll_rshift(llval.ull, lbits); /* truncated val */ + return llval.ull; +} + diff --git a/private/crt32/helper/mips/llcvt.s b/private/crt32/helper/mips/llcvt.s new file mode 100644 index 000000000..8a014eb1b --- /dev/null +++ b/private/crt32/helper/mips/llcvt.s @@ -0,0 +1,364 @@ +/* + * |-----------------------------------------------------------| + * | 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 <ksmips.h> + +#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 + diff --git a/private/crt32/helper/mips/lldefs.h b/private/crt32/helper/mips/lldefs.h new file mode 100644 index 000000000..41e6ee5ad --- /dev/null +++ b/private/crt32/helper/mips/lldefs.h @@ -0,0 +1,92 @@ + +/* + * |-----------------------------------------------------------| + * | 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: lldefs.h,v 3010.4 92/01/23 13:50:07 murphy Exp $ */ + +/* define double-word (long long) simulation routines for 32-bit code. */ + +#define long_long __int64 +typedef long_long longlong_t; +typedef unsigned long_long ulonglong_t; + +typedef struct { +/* _MIPSEL */ + unsigned lsw; + unsigned msw; +} dword; + +typedef union { + longlong_t ll; + ulonglong_t ull; + dword dw; +} llvalue; /* 64-bit integer values */ + +#define MSW(x) (x).dw.msw +#define LSW(x) (x).dw.lsw + +#define LL_ISNEG(x) ((signed)MSW(x) < 0) /* returns boolean */ + +/* relational operations; all take two llvalues and return boolean */ +#define LL_EQ(x,y) (LSW(x) == LSW(y) && MSW(x) == MSW(y)) +#define LL_NEQ(x,y) (LSW(x) != LSW(y) || MSW(x) != MSW(y)) +#define MSW_EQ(x,y) (MSW(x) == MSW(y)) +#define LL_LT(x,y) (MSW_EQ(x,y) ? (LSW(x) < LSW(y)) : ((int)MSW(x) < (int)MSW(y))) +#define ULL_LT(x,y) (MSW_EQ(x,y) ? (LSW(x) < LSW(y)) : (MSW(x) < MSW(y))) +#define LL_LE(x,y) (MSW_EQ(x,y) ? (LSW(x) <= LSW(y)) : ((int)MSW(x) < (int)MSW(y))) +#define ULL_LE(x,y) (MSW_EQ(x,y) ? (LSW(x) <= LSW(y)) : (MSW(x) < MSW(y))) +#define LL_GT(x,y) (MSW_EQ(x,y) ? (LSW(x) > LSW(y)) : ((int)MSW(x) > (int)MSW(y))) +#define ULL_GT(x,y) (MSW_EQ(x,y) ? (LSW(x) > LSW(y)) : (MSW(x) > MSW(y))) +#define LL_GE(x,y) (MSW_EQ(x,y) ? (LSW(x) >= LSW(y)) : ((int)MSW(x) > (int)MSW(y))) +#define ULL_GE(x,y) (MSW_EQ(x,y) ? (LSW(x) >= LSW(y)) : (MSW(x) > MSW(y))) + +/* these routines are actually statements! */ +#define LL_AND(r,x,y) MSW(r) = MSW(x) & MSW(y), LSW(r) = LSW(x) & LSW(y) +#define LL_OR(r,x,y) MSW(r) = MSW(x) | MSW(y), LSW(r) = LSW(x) | LSW(y) +#define LL_XOR(r,x,y) MSW(r) = MSW(x) ^ MSW(y), LSW(r) = LSW(x) ^ LSW(y) +#define LL_NOT(r,x) MSW(r) = ~MSW(x), LSW(r) = ~LSW(x) +#define LL_ADD(r,x,y) MSW(r) = MSW(x) + MSW(y) + ((LSW(x)+LSW(y)) < LSW(y)); LSW(r) = LSW(x) + LSW(y) +#define LL_SUB(r,x,y) MSW(r) = MSW(x) - MSW(y) - (LSW(x) < LSW(y)); LSW(r) = LSW(x) - LSW(y) +#define LL_NEG(r,x) MSW(r) = ~MSW(x) + (LSW(x) == 0); LSW(r) = -LSW(x) +#define SET_LL(x,i) LSW(x) = i, MSW(x) = (i < 0 ? -1 : 0) + +/* external routines */ +extern longlong_t __ll_mul (longlong_t ll_value, longlong_t multiplier); +extern longlong_t __ll_lshift (longlong_t ll_value, long ll_lshift); +extern longlong_t __ll_rshift (longlong_t ll_value, long ll_rshift); +extern longlong_t __ull_rshift (ulonglong_t ull_value, long ll_rshift); +extern longlong_t __ll_div (longlong_t divident, longlong_t divisor); +extern ulonglong_t __ull_div (ulonglong_t divident, ulonglong_t divisor); +extern longlong_t __ll_rem (longlong_t divident, longlong_t divisor); +extern ulonglong_t __ull_rem (ulonglong_t divident, ulonglong_t divisor); +extern void __ull_divremi (ulonglong_t *quotient, ulonglong_t *remainder, ulonglong_t dividend, unsigned short divisor); +extern longlong_t __ll_mod (longlong_t ll_value, longlong_t modulus); +extern longlong_t __d_to_ll (double); +extern longlong_t __f_to_ll (float); +extern ulonglong_t __d_to_ull (double); +extern ulonglong_t __f_to_ull (float); +extern double __ll_to_d (longlong_t); +extern float __ll_to_f (longlong_t); +extern double __ull_to_d (ulonglong_t); +extern float __ull_to_f (ulonglong_t); +extern ulonglong_t __ull_bit_extract (ulonglong_t *addr, + unsigned start_bit, unsigned length); +extern ulonglong_t __ull_bit_insert (ulonglong_t *addr, + unsigned start_bit, unsigned length, ulonglong_t val); +extern longlong_t __ll_bit_extract (ulonglong_t *addr, + unsigned start_bit, unsigned length); +extern longlong_t __ll_bit_insert (ulonglong_t *addr, + unsigned start_bit, unsigned length, longlong_t val); + diff --git a/private/crt32/helper/mips/lldiv.c b/private/crt32/helper/mips/lldiv.c new file mode 100644 index 000000000..140dffabb --- /dev/null +++ b/private/crt32/helper/mips/lldiv.c @@ -0,0 +1,251 @@ +/* + * |-----------------------------------------------------------| + * | 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: lldiv.c,v 3010.7 92/01/29 16:02:33 murphy Exp $ */ + +#include "lldefs.h" + +/* + Make sure that the intrinsic bit shift routines are not used! + They are guaranteed to work only for shifts of 0-31 bits. + */ +#pragma function(__ll_lshift) +#pragma function(__ll_rshift) +#pragma function(__ull_rshift) + +extern void __ull_divrem_6416 (ulonglong_t *q, ulonglong_t *r, ulonglong_t n, ulonglong_t d); +extern void __ull_divrem_5353 (ulonglong_t *q, ulonglong_t *r, ulonglong_t n, ulonglong_t d); +static void __ull_divrem_6464 (llvalue *aquo, llvalue *arem, llvalue num, llvalue denom); + +#define pow2_16 65536 /* 2^16 */ +#define pow2_21 2097152 /* 2^(53-32) */ + +/* Given an unsigned64 number, return the number of left-shifts required + to normalize it (causing high-order digit to be 1) */ +static +unsigned +ll_firstbit(llvalue number) +{ + unsigned bias = 0; + + if (MSW(number) == 0) + { + if (LSW(number) != 0) + { + bias = 32; + while ((LSW(number) & 0x80000000) == 0) + { + bias++; + LSW(number) <<= 1; + } + } + } + else + { + while ((MSW(number) & 0x80000000) == 0) + { + bias++; + MSW(number) <<= 1; + } + } + + return bias; +} + +/* + * General (i.e., difficult) case of 64-bit unsigned division. + * Use this to handle cases where values are greater than can be + * represented with 53-bits of double floats. + * Modified from pl1 library. + */ +static +void +__ull_divrem_6464 (llvalue *aquo, llvalue *arem, llvalue num, llvalue denom) +{ + llvalue quo; + int n_bias, d_bias; + + /* Shift denom left so its first bit lines up with that of numerator */ + n_bias = ll_firstbit(num); + d_bias = ll_firstbit(denom); + if ((d_bias -= n_bias) > 0) { + denom.ll = __ll_lshift(denom.ll, d_bias); + } + + /* + "Long division" just like you did in elementary school, except that + by virtue of doing it in binary, we can guess the next digit simply + by comparing numerator and divisor. + + quo = 0; + repeat (1 + amount_we_shifted_denom_left) + { + quo <<= 1; + if (!(num < denom)) + { + num -= denom; + quo |= 1; + } + denom >>= 1; + } + */ + MSW(quo) = LSW(quo) = 0; + while (d_bias-- >= 0) + { + quo.ll = __ll_lshift(quo.ll, 1); + + if (ULL_GE(num, denom)) + { + LL_SUB(num, num, denom); /* num -= denom */ + LSW(quo) |= 1; + } + denom.ll = __ull_rshift(denom.ll, 1); + } + + *aquo = quo; + *arem = num; +} + + +extern longlong_t +__ll_div (longlong_t left, longlong_t right) +{ + llvalue a,b,q,r; + llvalue ll_2_16, ll_2_53; + int negate = 0; + a.ll = left; + b.ll = right; + SET_LL(ll_2_16, pow2_16); + MSW(ll_2_53) = pow2_21; LSW(ll_2_53) = 0; + if (LL_ISNEG(a)) { + /* make positive, but later negate the quotient */ + negate = !negate; + LL_NEG(a,a); + } + if (LL_ISNEG(b)) { + /* make positive, but later negate the quotient */ + negate = !negate; + LL_NEG(b,b); + } + /* dividend is positive */ + if (ULL_LT(b,ll_2_16)) { + /* divide 64 bits by 16 bits */ + __ull_divrem_6416(&q.ull,&r.ull,a.ull,b.ull); + } else if (ULL_LE(a,ll_2_53) && ULL_LE(b,ll_2_53)) { + /* do fp double divide */ + __ull_divrem_5353(&q.ull,&r.ull,a.ull,b.ull); + } else { + /* do full 64-bit divide */ + __ull_divrem_6464(&q,&r, a, b); + } + if (negate) { + LL_NEG(q,q); + } + return q.ll; +} + +extern ulonglong_t +__ull_div (ulonglong_t left, ulonglong_t right) +{ + llvalue a,b,q,r; + llvalue ll_2_16, ll_2_53; + a.ull = left; + b.ull = right; + SET_LL(ll_2_16, pow2_16); + MSW(ll_2_53) = pow2_21; LSW(ll_2_53) = 0; + if (ULL_LT(b,ll_2_16)) { + __ull_divrem_6416(&q.ull,&r.ull,left,right); + } else if (ULL_LE(a,ll_2_53) && ULL_LE(b,ll_2_53)) { + __ull_divrem_5353(&q.ull,&r.ull,left,right); + } else { + __ull_divrem_6464(&q,&r,a,b); + } + return q.ull; +} + +extern longlong_t +__ll_rem (longlong_t left, longlong_t right) +{ + llvalue a,b,q,r; + llvalue ll_2_16, ll_2_53; + int negate = 0; + a.ll = left; + b.ll = right; + SET_LL(ll_2_16, pow2_16); + MSW(ll_2_53) = pow2_21; LSW(ll_2_53) = 0; + if (LL_ISNEG(a)) { + /* make positive, but later negate the remainder */ + negate = !negate; + LL_NEG(a,a); + } + if (LL_ISNEG(b)) { + /* make positive, remainder only depends on sign of num */ + LL_NEG(b,b); + } + /* dividend is positive */ + if (ULL_LT(b,ll_2_16)) { + /* divide 64 bits by 16 bits */ + __ull_divrem_6416(&q.ull,&r.ull,a.ull,b.ull); + } else if (ULL_LE(a,ll_2_53) && ULL_LE(b,ll_2_53)) { + /* do fp double divide */ + __ull_divrem_5353(&q.ull,&r.ull,a.ull,b.ull); + } else { + /* do full 64-bit divide */ + __ull_divrem_6464(&q,&r, a, b); + } + if (negate) { + LL_NEG(r,r); + } + return r.ll; +} + +extern ulonglong_t +__ull_rem (ulonglong_t left, ulonglong_t right) +{ + llvalue a,b,q,r; + llvalue ll_2_16, ll_2_53; + a.ll = left; + b.ll = right; + SET_LL(ll_2_16, pow2_16); + MSW(ll_2_53) = pow2_21; LSW(ll_2_53) = 0; + if (ULL_LT(b,ll_2_16)) { + __ull_divrem_6416(&q.ull,&r.ull,left,right); + } else if (ULL_LE(a,ll_2_53) && ULL_LE(b,ll_2_53)) { + __ull_divrem_5353(&q.ull,&r.ull,left,right); + } else { + __ull_divrem_6464(&q,&r,a,b); + } + return r.ull; +} + +extern +longlong_t +__ll_mod (longlong_t left, longlong_t right) +{ + /* mod is similar to rem except that: + * 11 rem 5 == 1 == 11 mod 5 + * 11 rem -5 == 1, 11 mod -5 == -4 + * -11 rem 5 == -1, -11 mod 5 == 4 + * -11 rem -5 == -1 == -11 mod -5 + */ + llvalue b,r; + b.ll = right; + r.ll = __ll_rem(left,right); + if (LL_ISNEG(r) != LL_ISNEG(b)) { + LL_ADD(r,r,b); + } + return r.ll; +} + diff --git a/private/crt32/helper/mips/lldivrem.s b/private/crt32/helper/mips/lldivrem.s new file mode 100644 index 000000000..83320a490 --- /dev/null +++ b/private/crt32/helper/mips/lldivrem.s @@ -0,0 +1,237 @@ +/* + * |-----------------------------------------------------------| + * | 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: lldivrem.s,v 3010.3 92/01/29 15:27:35 murphy Exp $ */ + +#include <ksmips.h> + +/* __ull_divrem (unsigned long long *quotient, *remainder, dividend, divisor) */ + +#ifdef _MIPSEL +# define LSH 0 +# define MSH 2 +# define LQUO 0(a0) +# define MQUO 4(a0) +# define LREM 0(a1) +# define MREM 4(a1) +# define LDEN a2 +# define MDEN a3 +# define LSOR 16(sp) +# define MSOR 20(sp) +#endif +#ifdef _MIPSEB +# define MSH 0 +# define LSH 2 +# define MQUO 0(a0) +# define LQUO 4(a0) +# define MREM 0(a1) +# define LREM 4(a1) +# define MDEN a2 +# define LDEN a3 +# define MSOR 16(sp) +# define LSOR 20(sp) +#endif + +.text + +/* ulldivrem (unsigned long long *quotient, unsigned long long *remainder, + * unsigned long long dividend, unsigned long long divisor); */ +/* unsigned division */ +/* assume that dividend is 64bit positive value; + * divisor is 16bit positive value. */ +.globl __ull_divrem_6416 +.ent __ull_divrem_6416 +__ull_divrem_6416: + .frame sp, 0, ra + move t0, LDEN /* dividend */ + move t1, MDEN + lw t2, LSOR /* divisor */ + lw t3, MSOR + divu zero, t0, t2 /* early start for first case */ + /* test if both dividend and divisor are 32-bit values */ + sra t4, t0, 31 + bnez t3, 3f /* divisor not 32-bit */ + /* divisor is 32-bit */ + bnez t1, 1f /* dividend not 32-bit */ + /* simply use 32-bit divide instruction */ + mflo v0 + mfhi t4 + sw v0, LQUO + sw zero, MQUO + sw t4, LREM + sw zero, MREM + j ra + + /* divisor 32-bit, dividend not */ +1: srl t4, t2, 16 + bne t4, 0, 3f + + /* dividing 64-bit positive value by 16-bit unsigned value */ +/*#ifdef _MIPSEL*/ +/* sll v0, MDEN, 16*/ +/*#else*/ + move v0, MDEN +/*#endif*/ + srl v0, v0, 16 /* get 16-bit MSH value from MDEN */ + divu zero, v0, t2 + mflo v1 + mfhi v0 + sh v1, MSH+MQUO + sll v0, 16 +/*#ifdef _MIPSEB*/ + sll t0, MDEN, 16 +/*#else*/ +/* move t0, MDEN*/ +/*#endif*/ + srl t0, t0, 16 /* get 16-bit LSH value from MDEN */ + or v0, t0 + divu zero, v0, t2 + mflo v1 + mfhi v0 + sh v1, LSH+MQUO + sll v0, 16 +/*#ifdef _MIPSEL*/ +/* sll t0, LDEN, 16*/ +/*#else*/ + move t0, LDEN +/*#endif*/ + srl t0, t0, 16 /* get 16-bit MSH value from LDEN */ + or v0, t0 + divu zero, v0, t2 + mflo v1 + mfhi v0 + sh v1, MSH+LQUO + sll v0, 16 +/*#ifdef _MIPSEB*/ + sll t0, LDEN, 16 +/*#else*/ +/* move t0, LDEN*/ +/*#endif*/ + srl t0, t0, 16 /* get 16-bit LSH value from LDEN */ + or v0, t0 + divu zero, v0, t2 + mflo v1 + mfhi v0 + sh v1, LSH+LQUO + sw zero, MREM + sw v0, LREM + j ra + + /* if dividend < divisor then quo = 0, rem = dividend */ +3: lw t0, MSOR + bgtu MDEN, t0, 36f + bltu MDEN, t0, 32f + /* MDEN == MSOR */ + lw t0, LSOR + bgeu LDEN, t0, 36f +32: sw zero, LQUO + sw zero, MQUO + sw LDEN, LREM + sw MDEN, MREM + j ra + + /* dividend or divisor too big; have to do division the hard way */ +36: break 0 +.end __ull_divrem_6416 + +/* ulldivrem (unsigned long long *quotient, unsigned long long *remainder, + * unsigned long long dividend, unsigned long long divisor); */ +/* unsigned division */ +/* assume that dividend and divisor both fit in 53 bits, + * so do double fp divide. */ +.globl __ull_divrem_5353 +.ent __ull_divrem_5353 +__ull_divrem_5353: + .frame sp, 0, ra + move t0, LDEN /* dividend */ + move t1, MDEN + lw t2, LSOR /* divisor */ + lw t3, MSOR + +2: li.d $f8, 4294967296.0 + cfc1 v1, $31 + li t5, 1 + ctc1 t5, $31 + + mtc1 t0, $f0 + mtc1 t1, $f2 + cvt.d.w $f0 + cvt.d.w $f2 + bgez t0, 22f + add.d $f0, $f8 +22: mul.d $f2, $f8 + add.d $f0, $f2 + + mtc1 t2, $f4 + mtc1 t3, $f6 + cvt.d.w $f4 + cvt.d.w $f6 + bgez t2, 24f + add.d $f4, $f8 +24: mul.d $f6, $f8 + add.d $f4, $f6 + cfc1 t9, $31 + and t9, 4 + bne t9, 0, 3f + + div.d $f2, $f0, $f4 + li.d $f6, 4503599627370496.0 + mfc1 t9, $f3 + bgez t9, 26f + neg.d $f6 +26: add.d $f2, $f6 + mfc1 t4, $f2 + mfc1 t5, $f3 + and t5, 0x000fffff + + multu t4, t2 + mflo t6 + mfhi t7 + multu t4, t3 + mflo t8 + addu t7, t8 + multu t5, t2 + mflo t8 + addu t7, t8 + + sltu t9, t0, t6 + subu t6, t0, t6 + subu t7, t1, t7 + subu t7, t9 + + sw t4, LQUO + sw t5, MQUO + sw t6, LREM + sw t7, MREM + + ctc1 v1, $31 + j ra + + /* if dividend < divisor then quo = 0, rem = dividend */ +3: lw t0, MSOR + bgtu MDEN, t0, 36f + bltu MDEN, t0, 32f + /* MDEN == MSOR */ + lw t0, LSOR + bgeu LDEN, t0, 36f +32: sw zero, LQUO + sw zero, MQUO + sw LDEN, LREM + sw MDEN, MREM + j ra + + /* dividend or divisor too big; have to do division the hard way */ +36: break 0 +.end __ull_divrem_5353 diff --git a/private/crt32/helper/mips/llmul.s b/private/crt32/helper/mips/llmul.s new file mode 100644 index 000000000..612b2384c --- /dev/null +++ b/private/crt32/helper/mips/llmul.s @@ -0,0 +1,57 @@ +/* + * |-----------------------------------------------------------| + * | 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: llmul.s,v 3010.1 91/09/05 17:13:51 murphy Exp $ */ + +#include <ksmips.h> + +/* long long __ll_mul (long long a, long long b) */ + +#ifdef _MIPSEL +# define RLSW v0 +# define RMSW v1 +# define ALSW a0 +# define AMSW a1 +# define BLSW a2 +# define BMSW a3 +#else /* _MIPSEB */ +# define RMSW v0 +# define RLSW v1 +# define AMSW a0 +# define ALSW a1 +# define BMSW a2 +# define BLSW a3 +#endif + +.text + +/* note that result of AMSW * BMSW overflows 64bits, so it is ignored. */ + +.globl __ll_mul +.ent __ll_mul +__ll_mul: + .frame sp, 0, ra + multu ALSW, BLSW + mflo RLSW + mfhi RMSW + multu AMSW, BLSW + mflo t0 + addu RMSW, t0 + multu ALSW, BMSW + mflo t0 + addu RMSW, t0 + j ra +.end __ll_mul + diff --git a/private/crt32/helper/mips/llshift.s b/private/crt32/helper/mips/llshift.s new file mode 100644 index 000000000..e0f61cbc6 --- /dev/null +++ b/private/crt32/helper/mips/llshift.s @@ -0,0 +1,226 @@ +// TITLE("Large Integer Arithmetic") +//++ +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// largeint.s +// +// Abstract: +// +// This module implements __int64 arithmetic helper routines for the MIPS Compiler. +// +// +// Author: +// +// David N. Cutler (davec) 18-Apr-1990 +// +// Environment: +// +// Any mode. +// +// Revision History: +// +// This module is derived from largeint.s in ntos\rtl\mips\largeint.s +// +//-- + +#include "ksmips.h" + + SBTTL("int64 Shift Left") + +//++ +// +// LARGE_INTEGER +// RtlLargeIntegerShiftLeft ( +// IN LARGE_INTEGER LargeInteger, +// IN CCHAR ShiftCount +// ) +// +// Routine Description: +// +// This function shifts a signed large integer left by an unsigned +// integer modulo 64 and returns the shifted signed large integer +// result. +// +// N.B. No test is made for significant bits shifted out of the result. +// +// Arguments: +// +// LargeInteger (a0=LSW, a1=MSW) - Supplies the large integer to be shifted. +// +// ShiftCount (a2) - bits to shift +// +// Return Value: +// +// The large integer result is stored into (v0=LSW,v1=MSW). +// +//-- + + LEAF_ENTRY(__ll_lshift) + + and a2,a2,0x3f // truncate shift count mod 64 + +// +// Left shift the operand by the specified shift count. +// + + li t1,32 // compute right shift count + subu t1,t1,a2 // + bgtz t1,10f // if gtz, shift less that 32-bits + +// +// Shift count is greater than or equal 32 bits - low half of result is zero, +// high half is the low half shifted left by remaining count. +// + + sll v1,a0,a2 // set high half of result + move v0,zero // store low part of reuslt + j ra // return + +// +// Shift count is less than 32-bits - high half of result is the high half +// of operand shifted left by count combined with the low half of the operand +// shifted right, low half of result is the low half shifted left. +// + +10: move v0,a0 // set low half of result + sll v1,a1,a2 // shift high half left count bits + beq zero,a2,20f // if eq, no more shifts necessary + srl t0,v0,t1 // isolate shifted out bits of low half + sll v0,v0,a2 // shift low half left count bits + or v1,v1,t0 // combine bits for high half of result +20: j ra // return + + .end __ll_rshift + + SBTTL("int64 Logical Shift Right") +//++ +// +// LARGE_INTEGER +// RtlLargeIntegerShiftRight ( +// IN LARGE_INTEGER LargeInteger, +// IN CCHAR ShiftCount +// ) +// +// Routine Description: +// +// This function shifts an unsigned large integer right by an unsigned +// integer modulo 64 and returns the shifted unsigned large integer +// result. +// +// Arguments: +// +// LargeInteger (a0=LSW, a1=MSW) - Supplies the large integer to be shifted. +// +// ShiftCount (a2) - Supplies the right shift count. +// +// Return Value: +// +// The large integer result is stored into (v0=LSW,v1=MSW). +// +//-- + + LEAF_ENTRY(__ull_rshift) + + and a2,a2,0x3f // truncate shift count mod 64 + +// +// Right shift the operand by the specified shift count. +// + + li t1,32 // compute left shift count + subu t1,t1,a2 // + bgtz t1,10f // if gtz, shift less that 32-bits + +// +// Shift count is greater than or equal 32 bits - high half of result is +// zero, low half is the high half shifted right by remaining count. +// + + srl v0,a1,a2 // set low half of result + move v1,zero // store high part of result + j ra // return + +// +// Shift count is less than 32-bits - high half of result is the high half +// of operand shifted right by count, low half of result is the shifted out +// bits of the high half combined with the right shifted low half of the +// operand. +// + +10: move v1,a1 // set high half of result + srl v0,a0,a2 // shift low half right count bits + beq zero,a2,20f // if eq, no more shifts necessary + sll t0,a1,t1 // isolate shifted out bits of high half + srl v1,a1,a2 // shift high half right count bits + or v0,v0,t0 // combine bits for low half of result +20: j ra // return + + .end __ull_rshift + + SBTTL("int64 Arithmetic Shift Right") +//++ +// +// LARGE_INTEGER +// RtlLargeIntegerArithmeticShift ( +// IN LARGE_INTEGER LargeInteger, +// IN CCHAR ShiftCount +// ) +// +// Routine Description: +// +// This function shifts a signed large integer right by an unsigned +// integer modulo 64 and returns the shifted signed large integer +// result. +// +// Arguments: +// +// LargeInteger (a0=LSW, a1=MSW) - Supplies the large integer to be shifted. +// +// ShiftCount (a2) - Supplies the right shift count. +// +// Return Value: +// +// The large integer result is stored into (v0=LSW,v1=MSW). +// +//-- + + LEAF_ENTRY(__ll_rshift) + + and a2,a2,0x3f // truncate shift count mod 64 + +// +// Right shift the operand by the specified shift count. +// + + li t1,32 // compute left shift count + subu t1,t1,a2 // + bgtz t1,10f // if gtz, shift less that 32-bits + +// +// Shift count is greater than or equal 32 bits - high half of result is +// bit63 sign-extended, low half is the high half shifted right by remaining count. +// + + sra v0,a1,a2 // set low half of result + sra v1,a1,31 // set high half of result + j ra // return + +// +// Shift count is less than 32-bits - high half of result is the high half +// of operand shifted right by count, low half of result is the shifted out +// bits of the high half combined with the right shifted low half of the +// operand. +// + +10: move v1, a1 // set high half of result + srl v0,a0,a2 // shift low half right count bits + beq zero,a2,20f // if eq, no more shifts necessary + sll t0,a1,t1 // isolate shifted out bits of high half + sra v1,a1,a2 // shift high half right count bits + or v0,v0,t0 // combine bits for low half of result +20: j ra // return + + .end __ll_rshift diff --git a/private/crt32/helper/mips/llshiftt.c b/private/crt32/helper/mips/llshiftt.c new file mode 100644 index 000000000..8c46e8a4f --- /dev/null +++ b/private/crt32/helper/mips/llshiftt.c @@ -0,0 +1,146 @@ +typedef __int64 longlong_t; +typedef unsigned __int64 ulonglong_t; + +typedef struct { + + unsigned lsw; + unsigned msw; +} dword; + +typedef union { + longlong_t ll; + ulonglong_t ull; + dword dw; +} llvalue; + +extern longlong_t __ll_mul (longlong_t ll_value, longlong_t multiplier); +extern longlong_t __ll_lshift (longlong_t ll_value, long ll_lshift); +extern longlong_t __ll_rshift (longlong_t ll_value, long ll_rshift); +extern longlong_t __ull_rshift (ulonglong_t ull_value, long ll_rshift); +extern longlong_t __ll_div (longlong_t divident, longlong_t divisor); +extern ulonglong_t __ull_div (ulonglong_t divident, ulonglong_t divisor); +extern longlong_t __ll_rem (longlong_t divident, longlong_t divisor); +extern ulonglong_t __ull_rem (ulonglong_t divident, ulonglong_t divisor); +extern void __ull_divremi (ulonglong_t *quotient, ulonglong_t *remainder, ulonglong_t dividend, unsigned short divisor); +extern longlong_t __ll_mod (longlong_t ll_value, longlong_t modulus); +extern longlong_t __d_to_ll (double); +extern longlong_t __f_to_ll (float); +extern ulonglong_t __d_to_ull (double); +extern ulonglong_t __f_to_ull (float); +extern double __ll_to_d (longlong_t); +extern float __ll_to_f (longlong_t); +extern double __ull_to_d (ulonglong_t); +extern float __ull_to_f (ulonglong_t); +extern ulonglong_t __ull_bit_extract (ulonglong_t *addr, + unsigned start_bit, unsigned length); +extern ulonglong_t __ull_bit_insert (ulonglong_t *addr, + unsigned start_bit, unsigned length, ulonglong_t val); +extern longlong_t __ll_bit_extract (ulonglong_t *addr, + unsigned start_bit, unsigned length); +extern longlong_t __ll_bit_insert (ulonglong_t *addr, + unsigned start_bit, unsigned length, longlong_t val); + +#define MSW(x) (x).dw.msw +#define LSW(x) (x).dw.lsw + +llvalue llval; + +int main(int argc, char *argv[], char *env[]) +{ + int n,i,k, kk = 0; + llvalue lltmp1; + llvalue lltmp2; + + for (n = 0; n < 64; n++) { + + if (n < 32) { + MSW(llval) = 0; + LSW(llval) = 1 << i; + } else { + MSW(llval) = 1 << (i-32); + LSW(llval) = 0; + } + + /* Test left shift */ + for (i = 0, k = 0; i < 64; i++) { + lltmp1.ll = llval.ll << i; + if (i == 0) { + MSW(lltmp2) = MSW(llval); + LSW(lltmp2) = LSW(llval); + } else if (i < 32) { + MSW(lltmp2) = (MSW(llval) << i) | (((unsigned long)LSW(llval)) >> (32-i)); + LSW(lltmp2) = LSW(llval) << i; + } else { + MSW(lltmp2) = LSW(llval) << (i-32); + LSW(lltmp2) = 0; + } + if (lltmp1.ll != lltmp2.ll) { + if (!k++) + printf("\n"); + printf("(0x%8.8x%8.8x) << %d\t(0x%8.8x%8.8x) != (0x%8.8x%8.8x)\n", MSW(llval), LSW(llval), i, MSW(lltmp1), LSW(lltmp1), MSW(lltmp2), LSW(lltmp2) ); + } + } + + if (k) { + printf("\n\tLeft logical shift failed %d tests\n",k); + kk += k; + } + + /* Test right unsigned shift */ + for (i = 0, k = 0; i < 64; i++) { + lltmp1.ull = llval.ull >> i; + if (i == 0) { + MSW(lltmp2) = MSW(llval); + LSW(lltmp2) = LSW(llval); + } else if (i < 32) { + LSW(lltmp2) = (LSW(llval) >> i) | (((unsigned long)MSW(llval)) << (32-i)); + MSW(lltmp2) = ((unsigned long)MSW(llval)) >> i; + } else { + MSW(lltmp2) = 0; + LSW(lltmp2) = ((unsigned long)MSW(llval)) >> (i-32); + } + if (lltmp1.ll != lltmp2.ll) { + if (!k++) + printf("\n"); + printf("(0x%8.8x%8.8x) >> %d\t(0x%8.8x%8.8x) != (0x%8.8x%8.8x)\n", MSW(llval), LSW(llval), i, MSW(lltmp1), LSW(lltmp1), MSW(lltmp2), LSW(lltmp2) ); + } + } + + if (k) { + printf("\n\tRight logical shift failed %d tests\n",k); + k += k; + } + + /* Test right arithmetic shift */ + for (i = 0, k = 0; i < 64; i++) { + lltmp1.ll = llval.ll >> i; + if (i == 0) { + MSW(lltmp2) = MSW(llval); + LSW(lltmp2) = LSW(llval); + } else if (i < 32) { + LSW(lltmp2) = (LSW(llval) >> i) | ((MSW(llval) << (32-i))); + MSW(lltmp2) = MSW(llval) >> i; + } else { + MSW(lltmp2) = 0; + LSW(lltmp2) = MSW(llval) >> (i-32); + } + if (lltmp1.ll != lltmp2.ll) { + if (!k++) + printf("\n"); + printf("(0x%8.8x%8.8x) >> %d\t(0x%8.8x%8.8x) != (0x%8.8x%8.8x)\n", MSW(llval), LSW(llval), i, MSW(lltmp1), LSW(lltmp1), MSW(lltmp2), LSW(lltmp2) ); + } + } + + if (k) { + printf("\n\tRight arithmetic shift failed %d tests\n",k); + k += k; + } + + } + + if (kk) + printf("\n\t'%s' failed a total of %d tests...\n", argv[0], kk); + else + printf("\n\t'%s' passed all tests...\n", argv[0]); + +} diff --git a/private/crt32/helper/sources b/private/crt32/helper/sources new file mode 100644 index 000000000..93e496902 --- /dev/null +++ b/private/crt32/helper/sources @@ -0,0 +1,65 @@ +!IF 0 + +Copyright (c) 1989-1993 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=crt +MINORCOMP=helper + +TARGETNAME=helper +TARGETPATH=..\obj +TARGETTYPE=LIBRARY +386_STDCALL=0 + +!INCLUDE ..\crt32.def +C_DEFINES= $(C_DEFINES) -D_MIPSEL -D_WIN32_ + +SOURCES=empty.c + +MIPS_SOURCES= lldiv.c \ + llbit.c \ + llabsdiv.c \ + llcvt.s \ + lldivrem.s \ + llmul.s\ + llshift.s + + +PPC_SOURCES= dtoi.s \ + dtoi64.s \ + dtou.s \ + dtou64.s \ + i64div.s \ + i64rem.s \ + i64tod.s \ + itod.s \ + itof.s \ + restfpr.s \ + restgpr.s \ + savefpr.s \ + savegpr.s \ + svgprarg.s \ + u64div.s \ + u64rem.s \ + u64tod.s \ + utod.s \ + utof.s |