summaryrefslogtreecommitdiffstats
path: root/private/crt32/helper
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/helper')
-rw-r--r--private/crt32/helper/empty.c5
-rw-r--r--private/crt32/helper/makefile8
-rw-r--r--private/crt32/helper/mips/llabsdiv.c62
-rw-r--r--private/crt32/helper/mips/llbit.c127
-rw-r--r--private/crt32/helper/mips/llcvt.s364
-rw-r--r--private/crt32/helper/mips/lldefs.h92
-rw-r--r--private/crt32/helper/mips/lldiv.c251
-rw-r--r--private/crt32/helper/mips/lldivrem.s237
-rw-r--r--private/crt32/helper/mips/llmul.s57
-rw-r--r--private/crt32/helper/mips/llshift.s226
-rw-r--r--private/crt32/helper/mips/llshiftt.c146
-rw-r--r--private/crt32/helper/sources65
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